skynet-deploy 0.9.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|