skynet-deploy 0.9.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +38 -1
- data/lib/skynet/app.rb +13 -8
- data/lib/skynet/builder.rb +2 -2
- data/lib/skynet/builder/base.rb +79 -16
- data/lib/skynet/builder/jekyll.rb +1 -4
- data/lib/skynet/builder/static.rb +1 -4
- data/lib/skynet/cli.rb +6 -6
- data/lib/skynet/templates/config.yml +21 -6
- data/lib/skynet/version.rb +1 -1
- data/spec/skynet/builder/base_spec.rb +114 -31
- data/spec/skynet/builder/jekyll_spec.rb +6 -7
- data/spec/skynet/builder/static_spec.rb +10 -10
- data/spec/skynet/builder_spec.rb +5 -2
- metadata +23 -73
data/README.md
CHANGED
@@ -8,13 +8,50 @@ Skynet builds and deploys web sites on your VPS or bare metal server. It is trig
|
|
8
8
|
Current Builder Types
|
9
9
|
---------------------
|
10
10
|
|
11
|
-
1. Static.
|
11
|
+
1. Static. Copies the entire repository to the specified destination and then
|
12
|
+
removes the destination .git folder
|
12
13
|
1. Jekyll. Run jekyll on your repository. Entirely controlled by
|
13
14
|
site's `_config.yml`
|
14
15
|
|
15
16
|
Usage
|
16
17
|
-----
|
18
|
+
|
17
19
|
* Install Skynet: `$ gem install skynet-deploy`
|
18
20
|
* Install basic config file: `$ skynet config <first project name>`
|
19
21
|
* edit config file to add your repositories
|
22
|
+
* Run builder by hand to ensure everything works: `$ skynet build`
|
23
|
+
* Add `http://YOUR_SKYNET_SERVER/PROJECT_NAME` as a WebHook URL to your repository under `Admin -> Service Hooks`
|
20
24
|
* Start server: `$ skynet server`
|
25
|
+
|
26
|
+
Config file arguments
|
27
|
+
---------------------
|
28
|
+
|
29
|
+
### Required configuration variables for each project: ###
|
30
|
+
* `url` Value passed from post-receive hook to verify that the deploy
|
31
|
+
should happen
|
32
|
+
* `type` The builder type to invoke for this application
|
33
|
+
* Either `branch` and `destination` together or only `branches` must be specified
|
34
|
+
|
35
|
+
### Optional configuration variables: ###
|
36
|
+
* `key` SSH private key file to be used to clone and pull from private
|
37
|
+
repositories. Should be given as an absolute path
|
38
|
+
* `repository` The location to clone the repository from. This is
|
39
|
+
usually inferred from `url`, but can be overridden here
|
40
|
+
* `branch` The branch to be deployed
|
41
|
+
* `destination` Absolute path to the deployed application
|
42
|
+
* `branches` For when multiple branches should be deployed to this
|
43
|
+
machine (such as a production + staging strategy). `branches` is a
|
44
|
+
hash with keys being the branch name and values being the destination
|
45
|
+
|
46
|
+
Example Post-Receive Hook
|
47
|
+
-------------------------
|
48
|
+
|
49
|
+
Add this to your `.git/hooks/post-receive` file to use Skynet with
|
50
|
+
a git server other than GitHub.
|
51
|
+
|
52
|
+
read oldrev newrev refname
|
53
|
+
|
54
|
+
curl -d "payload={\"repository\":{\"url\":\"<<same path as in config.yml>>\"},\"before\":\"$oldrev\",\"after\":\"$newrev\",\"ref\":\"$refname\"}" http://YOUR_SKYNET_SERVER/PROJECT_NAME
|
55
|
+
|
56
|
+
The URL must be visible from the Skynet server, as it will pull a new
|
57
|
+
copy of the repository from this server.
|
data/lib/skynet/app.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
require 'json'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
3
4
|
|
4
5
|
module Skynet
|
5
6
|
|
@@ -11,10 +12,10 @@ module Skynet
|
|
11
12
|
|
12
13
|
post '/:app_name' do |app_name|
|
13
14
|
Skynet.logger.debug "params: #{params.inspect}"
|
14
|
-
payload = JSON.parse params[:payload]
|
15
|
-
config = settings.config[app_name]
|
16
|
-
if deployable?
|
17
|
-
Builder.build app_name, config
|
15
|
+
@payload = JSON.parse params[:payload]
|
16
|
+
@config = settings.config[app_name]
|
17
|
+
if deployable?
|
18
|
+
Builder.build app_name, @config, branch
|
18
19
|
else
|
19
20
|
Skynet.logger.warn "#{app_name} is not deployable"
|
20
21
|
end
|
@@ -23,12 +24,16 @@ module Skynet
|
|
23
24
|
|
24
25
|
private
|
25
26
|
|
26
|
-
def deployable?
|
27
|
-
|
28
|
-
config[:url] == payload['repository']['url'] &&
|
29
|
-
payload['ref'] == "refs/heads/#{config[:branch]}" &&
|
27
|
+
def deployable?
|
28
|
+
@config.present? &&
|
29
|
+
@config[:url] == @payload['repository']['url'] &&
|
30
30
|
payload['after'] !~ /^0{40}$/
|
31
31
|
end
|
32
|
+
|
33
|
+
def branch
|
34
|
+
@payload['ref'] =~ %r[^refs/heads/(.*)$]
|
35
|
+
$1
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
end
|
data/lib/skynet/builder.rb
CHANGED
@@ -5,8 +5,8 @@ module Skynet
|
|
5
5
|
autoload :Static, 'skynet/builder/static'
|
6
6
|
autoload :Jekyll, 'skynet/builder/jekyll'
|
7
7
|
|
8
|
-
def self.build(app, config)
|
9
|
-
for_app(app, config).build
|
8
|
+
def self.build(app, config, branch=nil)
|
9
|
+
for_app(app, config).build branch
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.for_app(app, config, type=nil)
|
data/lib/skynet/builder/base.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'active_model'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'uri'
|
2
4
|
|
3
5
|
module Skynet
|
4
6
|
module Builder
|
@@ -8,32 +10,55 @@ module Skynet
|
|
8
10
|
class Base
|
9
11
|
include ActiveModel::Validations
|
10
12
|
|
11
|
-
attr_accessor :app, :url, :branch, :destination, :type
|
12
|
-
attr_reader :source
|
13
|
+
attr_accessor :app, :url, :branch, :destination, :branches, :type, :repository
|
14
|
+
attr_reader :source, :key
|
13
15
|
|
14
|
-
validates_presence_of :app, :url, :branch, :destination
|
16
|
+
validates_presence_of :app, :url, :branch, :destination, :branches
|
15
17
|
validates_inclusion_of :type,
|
16
18
|
in: ALLOWED_BUILDERS,
|
17
19
|
message: "must be one of #{ALLOWED_BUILDERS}"
|
20
|
+
validate :branches_have_destinations
|
21
|
+
validate :key_is_readable, if: :key?
|
18
22
|
|
19
23
|
def initialize(app, config)
|
20
|
-
self.app
|
21
|
-
@config
|
24
|
+
self.app = app
|
25
|
+
@config = config
|
26
|
+
@source = File.join Dir.pwd, app, '.'
|
27
|
+
@key = config[:key]
|
28
|
+
|
29
|
+
if config[:branches].blank?
|
30
|
+
self.branches = { config[:branch] => config[:destination] }
|
31
|
+
else
|
32
|
+
self.branches = config[:branches]
|
33
|
+
end
|
34
|
+
self.branch = branches.first[0]
|
35
|
+
self.destination = branches.first[1]
|
22
36
|
self.url = config[:url]
|
23
|
-
self.branch = config[:branch]
|
24
|
-
self.destination = config[:destination]
|
25
37
|
self.type = config[:type]
|
26
|
-
|
38
|
+
self.repository = config[:repository]
|
27
39
|
end
|
28
40
|
|
29
|
-
def build
|
30
|
-
unless
|
31
|
-
|
32
|
-
|
33
|
-
raise ArgumentError
|
41
|
+
def build(branch=nil)
|
42
|
+
unless branch.blank?
|
43
|
+
return if branches[branch].blank?
|
44
|
+
self.branches = { branch => branches[branch] }
|
34
45
|
end
|
35
46
|
|
36
|
-
|
47
|
+
branches.each_pair do |branch, destination|
|
48
|
+
self.branch = branch.to_s
|
49
|
+
self.destination = destination
|
50
|
+
|
51
|
+
if valid?
|
52
|
+
Skynet.logger.info "#{type} running for #{app} (branch: #{branch})"
|
53
|
+
else
|
54
|
+
Skynet.logger.error "Configuration error for #{app} (branch: #{branch})"
|
55
|
+
Skynet.logger.error errors.full_messages.join '. '
|
56
|
+
raise ArgumentError
|
57
|
+
end
|
58
|
+
|
59
|
+
build_repository
|
60
|
+
execute
|
61
|
+
end
|
37
62
|
end
|
38
63
|
|
39
64
|
private
|
@@ -42,20 +67,58 @@ module Skynet
|
|
42
67
|
repo_exists? ? update_repo : create_repo
|
43
68
|
end
|
44
69
|
|
70
|
+
def remote_repository
|
71
|
+
repository || translate_url
|
72
|
+
end
|
73
|
+
|
74
|
+
def translate_url
|
75
|
+
uri = URI.parse url
|
76
|
+
if uri.host == 'github.com'
|
77
|
+
"git@github.com:#{uri.path.gsub %r[(^/)|(/$)|(\.git$)], ''}.git"
|
78
|
+
else
|
79
|
+
url
|
80
|
+
end
|
81
|
+
rescue URI::InvalidURIError
|
82
|
+
url
|
83
|
+
end
|
84
|
+
|
45
85
|
def create_repo
|
46
86
|
Skynet.logger.debug "Creating repository for #{app}"
|
47
87
|
Skynet.logger.debug `rm -rf #{source}`
|
48
|
-
|
88
|
+
if key?
|
89
|
+
Skynet.logger.info `ssh-agent bash -c 'ssh-add #{key}; git clone #{remote_repository} #{app}'; cd #{source}; git checkout #{branch}`
|
90
|
+
else
|
91
|
+
Skynet.logger.info `git clone #{remote_repository} #{app}; cd #{source}; git checkout #{branch}`
|
92
|
+
end
|
49
93
|
end
|
50
94
|
|
51
95
|
def update_repo
|
52
96
|
Skynet.logger.debug "Updating repository for #{app}"
|
53
|
-
|
97
|
+
if key?
|
98
|
+
Skynet.logger.info `cd #{source}; git checkout #{branch}; ssh-agent bash -c 'ssh-add #{key}; git pull origin #{branch}'`
|
99
|
+
else
|
100
|
+
Skynet.logger.info `cd #{source}; git checkout #{branch}; git pull origin #{branch}`
|
101
|
+
end
|
54
102
|
end
|
55
103
|
|
56
104
|
def repo_exists?
|
57
105
|
File.exist? File.join(source, '.git')
|
58
106
|
end
|
107
|
+
|
108
|
+
def branches_have_destinations
|
109
|
+
return if branches.blank?
|
110
|
+
branches.each_pair do |b, d|
|
111
|
+
errors.add(:branches, "#{b} must have a destination") unless d.present?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def key?
|
116
|
+
key.present?
|
117
|
+
end
|
118
|
+
|
119
|
+
def key_is_readable
|
120
|
+
errors.add(:key, 'must be present and readable') unless File.readable?(key)
|
121
|
+
end
|
59
122
|
end
|
60
123
|
end
|
61
124
|
end
|
@@ -4,10 +4,7 @@ module Skynet
|
|
4
4
|
module Builder
|
5
5
|
class Jekyll < Base
|
6
6
|
|
7
|
-
def
|
8
|
-
Skynet.logger.info "Jekyll running for #{app}..."
|
9
|
-
super
|
10
|
-
|
7
|
+
def execute
|
11
8
|
Skynet.logger.debug "PWD: #{Dir.pwd} Source: #{source} Destination: #{destination}"
|
12
9
|
Skynet.logger.info `jekyll #{source} #{destination}`
|
13
10
|
|
@@ -4,10 +4,7 @@ module Skynet
|
|
4
4
|
module Builder
|
5
5
|
class Static < Base
|
6
6
|
|
7
|
-
def
|
8
|
-
Skynet.logger.info "Static running for #{app}..."
|
9
|
-
super
|
10
|
-
|
7
|
+
def execute
|
11
8
|
Skynet.logger.debug "Removing #{destination}/*"
|
12
9
|
FileUtils.rm_rf Dir.glob(File.join destination, '*'), secure: true
|
13
10
|
|
data/lib/skynet/cli.rb
CHANGED
@@ -46,12 +46,12 @@ module Skynet
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
desc "build [PROJECT_NAME]", "Builds all applications, or PROJECT_NAME only if given"
|
49
|
+
desc "build [PROJECT_NAME] [BRANCH_NAME]", "Builds all applications, or PROJECT_NAME only if given"
|
50
50
|
method_option :file, type: :string, default: './config.yml', aliases: '-f', desc: 'Configuration file'
|
51
|
-
def build(
|
51
|
+
def build(project=nil, branch=nil)
|
52
52
|
all_apps = load_configuration options[:file]
|
53
53
|
|
54
|
-
if
|
54
|
+
if project.nil?
|
55
55
|
all_apps.each do |app, config|
|
56
56
|
begin
|
57
57
|
Builder.build app, config
|
@@ -60,11 +60,11 @@ module Skynet
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
else
|
63
|
-
config = all_apps[
|
63
|
+
config = all_apps[project]
|
64
64
|
if config.nil?
|
65
|
-
Skynet.logger.error "Could not find configuration for #{
|
65
|
+
Skynet.logger.error "Could not find configuration for #{project}"
|
66
66
|
else
|
67
|
-
Builder.build
|
67
|
+
Builder.build project, config, branch
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -1,15 +1,30 @@
|
|
1
|
-
# Base configuration for
|
2
|
-
#
|
3
|
-
# Example project:
|
1
|
+
# Base configuration for Skynet
|
4
2
|
#
|
3
|
+
# Example for single branch deployment:
|
5
4
|
# project_name:
|
6
|
-
# url:
|
7
|
-
# branch: master
|
5
|
+
# url: https://github.com/owner/project_name
|
8
6
|
# type: jekyll
|
7
|
+
# branch: master
|
9
8
|
# destination: /var/www/project_name
|
9
|
+
#
|
10
|
+
# Example for multiple branch deployment:
|
11
|
+
# project_name:
|
12
|
+
# url: https://github.com/owner/project_name
|
13
|
+
# type: jekyll
|
14
|
+
# branches:
|
15
|
+
# master: /var/www/project_name_production
|
16
|
+
# develop: /var/www/project_name_staging
|
17
|
+
#
|
18
|
+
# Example for private repository deployment:
|
19
|
+
# project_name:
|
20
|
+
# url: https://github.com/owner/project_name
|
21
|
+
# type: jekyll
|
22
|
+
# key: /home/username/.ssh/id_rsa
|
23
|
+
# branch: master
|
24
|
+
# destination: /var/www/project_name
|
10
25
|
|
11
26
|
<%= @project_name %>:
|
12
|
-
url: https://github.com/
|
27
|
+
url: https://github.com/ORGANIZATION_OR_USER/<%= @project_name %>
|
13
28
|
branch: master
|
14
29
|
type:
|
15
30
|
destination:
|
data/lib/skynet/version.rb
CHANGED
@@ -5,8 +5,9 @@ require 'shoulda-matchers'
|
|
5
5
|
describe Skynet::Builder::Base do
|
6
6
|
|
7
7
|
let(:source) { File.join Dir.pwd, 'app', '.' }
|
8
|
-
let(:
|
9
|
-
let(:
|
8
|
+
let(:url) { 'https://github.com/org/app' }
|
9
|
+
let(:repo) { 'git@github.com:org/app.git' }
|
10
|
+
let(:options) { {url: url, branch: 'master', destination: '/var/www', type: 'static'} }
|
10
11
|
subject { described_class.new 'app', options }
|
11
12
|
|
12
13
|
describe ".validations" do
|
@@ -14,61 +15,143 @@ describe Skynet::Builder::Base do
|
|
14
15
|
it { should validate_presence_of :url }
|
15
16
|
it { should validate_presence_of :branch }
|
16
17
|
it { should validate_presence_of :destination }
|
18
|
+
it { should validate_presence_of :branches }
|
17
19
|
it { should ensure_inclusion_of(:type).in_array(%w[static jekyll]).allow_nil(false).allow_blank(false) }
|
18
20
|
it { should_not allow_value('base').for :type }
|
21
|
+
describe "on @branches" do
|
22
|
+
before(:each) { subject.valid? }
|
23
|
+
|
24
|
+
context "when passed a single branch" do
|
25
|
+
specify { subject.errors[:branches].should be_empty }
|
26
|
+
end
|
27
|
+
context "when passed multiple valid branches" do
|
28
|
+
let(:options) { {url: url, type: 'static', branches: {master: '/var/www/production', develop: '/var/www/staging'}} }
|
29
|
+
specify { subject.errors[:branches].should be_empty }
|
30
|
+
end
|
31
|
+
context "when passed an invalid branch" do
|
32
|
+
let(:options) { {url: url, type: 'static', branches: {master: '/var/www', develop: ''}} }
|
33
|
+
it "has an error on branches" do
|
34
|
+
subject.errors[:branches].should include('develop must have a destination')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
describe "on @key" do
|
39
|
+
context "when not passed a key" do
|
40
|
+
before(:each) { subject.valid? }
|
41
|
+
specify { subject.errors[:key].should be_empty }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when passed a valid key" do
|
45
|
+
let(:options) { {key: 'keyfile'} }
|
46
|
+
before(:each) do
|
47
|
+
File.stub(:readable?).and_return true
|
48
|
+
subject.valid?
|
49
|
+
end
|
50
|
+
specify { subject.errors[:key].should be_empty }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when passed an invalid key" do
|
54
|
+
let(:options) { {key: 'missing_keyfile'} }
|
55
|
+
before(:each) do
|
56
|
+
File.stub(:readable?).and_return false
|
57
|
+
subject.valid?
|
58
|
+
end
|
59
|
+
it "has an error on key" do
|
60
|
+
subject.errors[:key].should include('must be present and readable')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
19
64
|
end
|
20
65
|
|
21
66
|
describe "#build" do
|
67
|
+
before(:each) do
|
68
|
+
subject.stub :build_repository
|
69
|
+
subject.stub :execute
|
70
|
+
end
|
71
|
+
|
22
72
|
context "when valid" do
|
23
|
-
before(:each) { subject.stub :build_repository }
|
24
73
|
it { expect { subject.build }.to_not raise_error }
|
25
74
|
end
|
26
75
|
context "when invalid" do
|
27
76
|
let(:options) { {} }
|
28
77
|
it { expect { subject.build }.to raise_error ArgumentError }
|
29
78
|
end
|
79
|
+
context "when passing a branch" do
|
80
|
+
it { expect { subject.build 'master' }.to_not raise_error }
|
81
|
+
it "d" do
|
82
|
+
subject.build 'develop'
|
83
|
+
end
|
84
|
+
end
|
30
85
|
end
|
31
86
|
|
32
|
-
|
33
|
-
|
34
|
-
|
87
|
+
context "private methods" do
|
88
|
+
before(:each) do
|
89
|
+
subject.branch = 'master'
|
90
|
+
subject.destination = '/var/www'
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#build_repository" do
|
94
|
+
context "repo already exists" do
|
95
|
+
before(:each) { subject.stub(:repo_exists?).and_return true }
|
35
96
|
|
36
|
-
|
37
|
-
|
38
|
-
|
97
|
+
it "updates the repository" do
|
98
|
+
subject.should_receive(:update_repo).with no_args
|
99
|
+
subject.send :build_repository
|
100
|
+
end
|
39
101
|
end
|
40
|
-
end
|
41
102
|
|
42
|
-
|
43
|
-
|
103
|
+
context "repo does not exist" do
|
104
|
+
before(:each) { subject.stub(:repo_exists?).and_return false }
|
44
105
|
|
45
|
-
|
46
|
-
|
47
|
-
|
106
|
+
it "creates a new repository" do
|
107
|
+
subject.should_receive(:create_repo).with no_args
|
108
|
+
subject.send :build_repository
|
109
|
+
end
|
48
110
|
end
|
49
111
|
end
|
50
|
-
end
|
51
112
|
|
52
|
-
|
53
|
-
|
54
|
-
subject.should_receive(:`).with "rm -rf #{source}"
|
55
|
-
subject.should_receive(:`).with "git clone #{repo} app; cd #{source}; git checkout master"
|
56
|
-
end
|
113
|
+
describe "#create_repo" do
|
114
|
+
before(:each) { subject.should_receive(:`).with "rm -rf #{source}" }
|
57
115
|
|
58
|
-
|
59
|
-
|
116
|
+
context "without key" do
|
117
|
+
it "should call git clone" do
|
118
|
+
subject.should_receive(:`).with "git clone #{repo} app; cd #{source}; git checkout master"
|
119
|
+
subject.send :create_repo
|
120
|
+
end
|
121
|
+
end
|
60
122
|
|
61
|
-
|
62
|
-
|
123
|
+
context "with key" do
|
124
|
+
let(:options) { {key: 'keyfile', url: url, branch: 'master', destination: '/var/www', type: 'static'} }
|
125
|
+
it "should call git clone" do
|
126
|
+
subject.should_receive(:`).with "ssh-agent bash -c 'ssh-add keyfile; git clone #{repo} app'; cd #{source}; git checkout master"
|
127
|
+
subject.send :create_repo
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
63
131
|
|
64
|
-
|
65
|
-
|
132
|
+
describe "#update_repo" do
|
133
|
+
context "without key" do
|
134
|
+
it "should call git pull" do
|
135
|
+
subject.should_receive(:`).with "cd #{source}; git checkout master; git pull origin master"
|
136
|
+
subject.send :update_repo
|
137
|
+
end
|
138
|
+
end
|
66
139
|
|
67
|
-
|
68
|
-
|
69
|
-
|
140
|
+
context "with key" do
|
141
|
+
let(:options) { {key: 'keyfile', url: url, branch: 'master', destination: '/var/www', type: 'static'} }
|
142
|
+
it "should call git pull" do
|
143
|
+
subject.should_receive(:`).with "cd #{source}; git checkout master; ssh-agent bash -c 'ssh-add keyfile; git pull origin master'"
|
144
|
+
subject.send :update_repo
|
145
|
+
end
|
146
|
+
end
|
70
147
|
end
|
71
148
|
|
72
|
-
|
149
|
+
describe "#repo_exists?" do
|
150
|
+
before(:each) do
|
151
|
+
File.should_receive(:exist?).with File.join(source, '.git')
|
152
|
+
end
|
153
|
+
|
154
|
+
it { subject.send :repo_exists? }
|
155
|
+
end
|
73
156
|
end
|
74
157
|
end
|
@@ -6,17 +6,16 @@ describe Skynet::Builder::Jekyll do
|
|
6
6
|
let(:dest) { '/var/www/app' }
|
7
7
|
let(:options) { {destination: dest} }
|
8
8
|
let(:source) { File.join Dir.pwd, app, '.' }
|
9
|
-
subject
|
10
|
-
|
11
|
-
|
12
|
-
before(:each) do
|
13
|
-
subject.should_receive :build_repository
|
14
|
-
subject.stub(:valid?).and_return true
|
9
|
+
subject do
|
10
|
+
described_class.new(app, options).tap do |b|
|
11
|
+
b.destination = dest
|
15
12
|
end
|
13
|
+
end
|
16
14
|
|
15
|
+
describe "#execute" do
|
17
16
|
it "runs jekyll with the source and destination" do
|
18
17
|
subject.should_receive(:`).with "jekyll #{source} #{dest}"
|
19
|
-
subject.
|
18
|
+
subject.execute
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -6,34 +6,34 @@ describe Skynet::Builder::Static do
|
|
6
6
|
let(:dest) { '/var/www/app' }
|
7
7
|
let(:options) { {destination: dest} }
|
8
8
|
let(:source) { File.join Dir.pwd, app, '.' }
|
9
|
-
subject
|
10
|
-
|
11
|
-
|
12
|
-
before(:each) do
|
13
|
-
subject.should_receive :build_repository
|
14
|
-
subject.stub(:valid?).and_return true
|
15
|
-
Dir.stub(:glob).and_return [:one, :two]
|
9
|
+
subject do
|
10
|
+
described_class.new(app, options).tap do |b|
|
11
|
+
b.destination = dest
|
16
12
|
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#execute" do
|
16
|
+
before(:each) { Dir.stub(:glob).and_return [:one, :two] }
|
17
17
|
|
18
18
|
it "removes destination files first" do
|
19
19
|
FileUtils.stub :remove_entry_secure
|
20
20
|
FileUtils.stub :cp_r
|
21
21
|
FileUtils.should_receive(:rm_rf).with [:one, :two], secure: true
|
22
|
-
subject.
|
22
|
+
subject.execute
|
23
23
|
end
|
24
24
|
|
25
25
|
it "copies files to the destination" do
|
26
26
|
FileUtils.stub :rm_rf
|
27
27
|
FileUtils.stub :remove_entry_secure
|
28
28
|
FileUtils.should_receive(:cp_r).with(source, dest)
|
29
|
-
subject.
|
29
|
+
subject.execute
|
30
30
|
end
|
31
31
|
|
32
32
|
it "removes .git from the destination" do
|
33
33
|
FileUtils.stub :rm_rf
|
34
34
|
FileUtils.stub :cp_r
|
35
35
|
FileUtils.should_receive(:remove_entry_secure).with "#{dest}/.git"
|
36
|
-
subject.
|
36
|
+
subject.execute
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/spec/skynet/builder_spec.rb
CHANGED
@@ -5,9 +5,10 @@ describe Skynet::Builder do
|
|
5
5
|
let(:builder) { mock('builder').as_null_object }
|
6
6
|
let(:mock_class) { mock('builder class').as_null_object }
|
7
7
|
let(:config) { {type: 'static'} }
|
8
|
-
let(:args) { [:app, config] }
|
9
8
|
|
10
9
|
describe ".for_app" do
|
10
|
+
let(:args) { [:app, config] }
|
11
|
+
|
11
12
|
it "initializes a new builder class" do
|
12
13
|
described_class.should_receive(:const_get).with('Static').and_return mock_class
|
13
14
|
mock_class.should_receive(:new).with(:app, config).and_return builder
|
@@ -17,9 +18,11 @@ describe Skynet::Builder do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
describe ".build" do
|
21
|
+
let(:args) { [:app, config, :master] }
|
22
|
+
|
20
23
|
it "calls build on the new builder" do
|
21
24
|
described_class.stub(:for_app).and_return builder
|
22
|
-
builder.should_receive(:build).with
|
25
|
+
builder.should_receive(:build).with :master
|
23
26
|
|
24
27
|
described_class.build *args
|
25
28
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skynet-deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-07 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70212012481880 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,15 +21,10 @@ dependencies:
|
|
21
21
|
version: '1.3'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.3'
|
24
|
+
version_requirements: *70212012481880
|
30
25
|
- !ruby/object:Gem::Dependency
|
31
26
|
name: thin
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
27
|
+
requirement: &70212012481240 !ruby/object:Gem::Requirement
|
33
28
|
none: false
|
34
29
|
requirements:
|
35
30
|
- - ~>
|
@@ -37,15 +32,10 @@ dependencies:
|
|
37
32
|
version: '1.4'
|
38
33
|
type: :runtime
|
39
34
|
prerelease: false
|
40
|
-
version_requirements:
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '1.4'
|
35
|
+
version_requirements: *70212012481240
|
46
36
|
- !ruby/object:Gem::Dependency
|
47
37
|
name: json
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &70212012480460 !ruby/object:Gem::Requirement
|
49
39
|
none: false
|
50
40
|
requirements:
|
51
41
|
- - ~>
|
@@ -53,15 +43,10 @@ dependencies:
|
|
53
43
|
version: '1.7'
|
54
44
|
type: :runtime
|
55
45
|
prerelease: false
|
56
|
-
version_requirements:
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.7'
|
46
|
+
version_requirements: *70212012480460
|
62
47
|
- !ruby/object:Gem::Dependency
|
63
48
|
name: jekyll
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirement: &70212012479780 !ruby/object:Gem::Requirement
|
65
50
|
none: false
|
66
51
|
requirements:
|
67
52
|
- - ~>
|
@@ -69,15 +54,10 @@ dependencies:
|
|
69
54
|
version: '0.11'
|
70
55
|
type: :runtime
|
71
56
|
prerelease: false
|
72
|
-
version_requirements:
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0.11'
|
57
|
+
version_requirements: *70212012479780
|
78
58
|
- !ruby/object:Gem::Dependency
|
79
59
|
name: thor
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirement: &70212012479240 !ruby/object:Gem::Requirement
|
81
61
|
none: false
|
82
62
|
requirements:
|
83
63
|
- - ~>
|
@@ -85,15 +65,10 @@ dependencies:
|
|
85
65
|
version: '0.16'
|
86
66
|
type: :runtime
|
87
67
|
prerelease: false
|
88
|
-
version_requirements:
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0.16'
|
68
|
+
version_requirements: *70212012479240
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
70
|
name: activesupport
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirement: &70212012478540 !ruby/object:Gem::Requirement
|
97
72
|
none: false
|
98
73
|
requirements:
|
99
74
|
- - ~>
|
@@ -101,15 +76,10 @@ dependencies:
|
|
101
76
|
version: '3.2'
|
102
77
|
type: :runtime
|
103
78
|
prerelease: false
|
104
|
-
version_requirements:
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ~>
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '3.2'
|
79
|
+
version_requirements: *70212012478540
|
110
80
|
- !ruby/object:Gem::Dependency
|
111
81
|
name: activemodel
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
82
|
+
requirement: &70212012477820 !ruby/object:Gem::Requirement
|
113
83
|
none: false
|
114
84
|
requirements:
|
115
85
|
- - ~>
|
@@ -117,15 +87,10 @@ dependencies:
|
|
117
87
|
version: '3.2'
|
118
88
|
type: :runtime
|
119
89
|
prerelease: false
|
120
|
-
version_requirements:
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ~>
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '3.2'
|
90
|
+
version_requirements: *70212012477820
|
126
91
|
- !ruby/object:Gem::Dependency
|
127
92
|
name: rake
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirement: &70212012477360 !ruby/object:Gem::Requirement
|
129
94
|
none: false
|
130
95
|
requirements:
|
131
96
|
- - ~>
|
@@ -133,15 +98,10 @@ dependencies:
|
|
133
98
|
version: '0.9'
|
134
99
|
type: :development
|
135
100
|
prerelease: false
|
136
|
-
version_requirements:
|
137
|
-
none: false
|
138
|
-
requirements:
|
139
|
-
- - ~>
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: '0.9'
|
101
|
+
version_requirements: *70212012477360
|
142
102
|
- !ruby/object:Gem::Dependency
|
143
103
|
name: rspec
|
144
|
-
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirement: &70212012476820 !ruby/object:Gem::Requirement
|
145
105
|
none: false
|
146
106
|
requirements:
|
147
107
|
- - ~>
|
@@ -149,15 +109,10 @@ dependencies:
|
|
149
109
|
version: '2.11'
|
150
110
|
type: :development
|
151
111
|
prerelease: false
|
152
|
-
version_requirements:
|
153
|
-
none: false
|
154
|
-
requirements:
|
155
|
-
- - ~>
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
version: '2.11'
|
112
|
+
version_requirements: *70212012476820
|
158
113
|
- !ruby/object:Gem::Dependency
|
159
114
|
name: shoulda-matchers
|
160
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirement: &70212012476100 !ruby/object:Gem::Requirement
|
161
116
|
none: false
|
162
117
|
requirements:
|
163
118
|
- - ~>
|
@@ -165,12 +120,7 @@ dependencies:
|
|
165
120
|
version: '1.2'
|
166
121
|
type: :development
|
167
122
|
prerelease: false
|
168
|
-
version_requirements:
|
169
|
-
none: false
|
170
|
-
requirements:
|
171
|
-
- - ~>
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '1.2'
|
123
|
+
version_requirements: *70212012476100
|
174
124
|
description: Sinatra app that listens for GitHub post-receive callbacks and deploys
|
175
125
|
your code
|
176
126
|
email:
|
@@ -222,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
172
|
version: 1.3.6
|
223
173
|
requirements: []
|
224
174
|
rubyforge_project:
|
225
|
-
rubygems_version: 1.8.
|
175
|
+
rubygems_version: 1.8.10
|
226
176
|
signing_key:
|
227
177
|
specification_version: 3
|
228
178
|
summary: Sinatra app that listens for GitHub post-receive callbacks and deploys your
|