vigil 0.1
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/CHANGES +3 -0
- data/Gemfile +17 -0
- data/README.md +48 -0
- data/Rakefile +8 -0
- data/bin/vigil +19 -0
- data/lib/vigil.rb +61 -0
- data/lib/vigil/git.rb +17 -0
- data/lib/vigil/os.rb +37 -0
- data/lib/vigil/pipeline.rb +37 -0
- data/lib/vigil/project.rb +23 -0
- data/lib/vigil/revision.rb +73 -0
- data/lib/vigil/revision_repository.rb +19 -0
- data/lib/vigil/test_pipeline.rb +26 -0
- data/lib/vigil/vagrant.rb +13 -0
- data/lib/vigil/version.rb +3 -0
- data/lib/vigil/vmbuilder.rb +102 -0
- data/spec/lib/vigil/pipeline_spec.rb +40 -0
- data/spec/lib/vigil/revision_repository_spec.rb +29 -0
- data/spec/lib/vigil/vmbuilder_spec.rb +129 -0
- data/spec/lib/vigil_spec.rb +5 -0
- data/spec/spec_helper.rb +2 -0
- metadata +130 -0
data/CHANGES
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "vagrant"
|
4
|
+
gem "veewee"
|
5
|
+
gem "trollop"
|
6
|
+
gem "plugman"
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem "rake"
|
10
|
+
gem "rspec"
|
11
|
+
gem "guard-rspec"
|
12
|
+
|
13
|
+
if RUBY_PLATFORM.downcase.include?("darwin")
|
14
|
+
gem 'rb-fsevent'
|
15
|
+
gem 'terminal-notifier-guard'
|
16
|
+
end
|
17
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
VIGIL
|
2
|
+
=====
|
3
|
+
[](http://travis-ci.org/kjellm/vigil)
|
4
|
+
[](https://codeclimate.com/github/kjellm/vigil)
|
5
|
+
|
6
|
+
|
7
|
+
A continous deploy pipeline
|
8
|
+
|
9
|
+
See also
|
10
|
+
--------
|
11
|
+
|
12
|
+
- [vigil-web][]
|
13
|
+
|
14
|
+
|
15
|
+
[vigil-web]: https://github.com/kjellm/vigil-web
|
16
|
+
|
17
|
+
Bugs
|
18
|
+
----
|
19
|
+
|
20
|
+
Report bugs to <https://github.com/kjellm/vigil/issues>.
|
21
|
+
|
22
|
+
|
23
|
+
Author
|
24
|
+
------
|
25
|
+
|
26
|
+
Kjell-Magne Øierud <kjellm AT oierud DOT net>
|
27
|
+
|
28
|
+
License
|
29
|
+
-------
|
30
|
+
|
31
|
+
(The MIT License)
|
32
|
+
|
33
|
+
Copyright © 2013 Kjell-Magne Øierud
|
34
|
+
|
35
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
36
|
+
associated documentation files (the ‘Software’), to deal in the Software without restriction, including
|
37
|
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
38
|
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
|
39
|
+
the following conditions:
|
40
|
+
|
41
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
42
|
+
portions of the Software.
|
43
|
+
|
44
|
+
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
45
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
46
|
+
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
47
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
48
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/vigil
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'trollop'
|
4
|
+
require 'vigil'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
opts = Trollop::options do
|
8
|
+
opt :rcfile, "Path to the configuration file"
|
9
|
+
end
|
10
|
+
|
11
|
+
root = File.join(File.dirname(__FILE__), '..')
|
12
|
+
if !opts[:rcfile] and File.exists?(File.join(root, '.git'))
|
13
|
+
opts[:rcfile] = File.join root, 'vigil.yml'
|
14
|
+
end
|
15
|
+
|
16
|
+
opts = YAML.load_file(opts[:rcfile]).merge(opts)
|
17
|
+
|
18
|
+
Vigil.new(opts).run
|
19
|
+
|
data/lib/vigil.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'plugman'
|
2
|
+
require 'vigil/git'
|
3
|
+
require 'vigil/os'
|
4
|
+
require 'vigil/pipeline'
|
5
|
+
require 'vigil/test_pipeline'
|
6
|
+
require 'vigil/project'
|
7
|
+
require 'vigil/revision'
|
8
|
+
require 'vigil/revision_repository'
|
9
|
+
require 'vigil/vagrant'
|
10
|
+
require 'vigil/vmbuilder'
|
11
|
+
|
12
|
+
class Vigil
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr :os, true
|
16
|
+
attr :run_dir, true
|
17
|
+
attr :plugman, true
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(args)
|
21
|
+
@x = args[:os] || Vigil::OS.new
|
22
|
+
Vigil.os = @x
|
23
|
+
Vigil.run_dir = File.expand_path 'run'
|
24
|
+
Vigil.plugman = Plugman.new(plugins: [])
|
25
|
+
_initialize_projects(args[:projects] || [])
|
26
|
+
end
|
27
|
+
|
28
|
+
def _initialize_projects(projects)
|
29
|
+
@projects = projects.map do |p|
|
30
|
+
Project.new(
|
31
|
+
name: p[:name],
|
32
|
+
git_url: p[:git][:url],
|
33
|
+
branch: p[:git][:branch]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
@x.mkdir_p Vigil.run_dir
|
40
|
+
loop do
|
41
|
+
_less_often_than_every(60) do
|
42
|
+
puts "### Vigil loop"
|
43
|
+
@projects.each do |p|
|
44
|
+
puts "## #{p.inspect}"
|
45
|
+
p.run_pipeline
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def _less_often_than_every(n_seconds)
|
52
|
+
start = Time.now
|
53
|
+
yield
|
54
|
+
_end = Time.now
|
55
|
+
if _end - start < n_seconds
|
56
|
+
n = n_seconds - (_end - start)
|
57
|
+
puts "Sleeping for #{n} sec."
|
58
|
+
sleep n
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/vigil/git.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Vigil
|
2
|
+
module Git
|
3
|
+
|
4
|
+
def self.clone(url, target)
|
5
|
+
Vigil.os._system "git clone #{url} #{target}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.checkout(branch)
|
9
|
+
Vigil.os._system "git checkout #{branch}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.differs?(rev_spec, files)
|
13
|
+
!Vigil.os.__system "git diff --quiet #{rev_spec} -- #{files}"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/vigil/os.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
class Vigil
|
3
|
+
class OS
|
4
|
+
|
5
|
+
def _system cmd
|
6
|
+
puts "# #{cmd}"
|
7
|
+
system cmd or raise "Failed"
|
8
|
+
end
|
9
|
+
|
10
|
+
def __system cmd
|
11
|
+
puts "# #{cmd}"
|
12
|
+
system cmd
|
13
|
+
return $? == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def mkdir_p *args
|
17
|
+
FileUtils.mkdir_p *args
|
18
|
+
end
|
19
|
+
|
20
|
+
def chdir *args
|
21
|
+
Dir.chdir *args
|
22
|
+
end
|
23
|
+
|
24
|
+
def exists? *args
|
25
|
+
File.exists? *args
|
26
|
+
end
|
27
|
+
|
28
|
+
def ln *args
|
29
|
+
FileUtils.ln *args
|
30
|
+
end
|
31
|
+
|
32
|
+
def entries *args
|
33
|
+
Dir.entries *args
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Vigil
|
2
|
+
class Pipeline
|
3
|
+
|
4
|
+
def initialize(revision, args={})
|
5
|
+
@os = Vigil.os
|
6
|
+
@revision = revision
|
7
|
+
@vmbuilder = args[:vmbuilder] || VMBuilder.new(@revision)
|
8
|
+
@plugman = Vigil.plugman
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
@os.chdir @revision.working_dir
|
13
|
+
_git_clone
|
14
|
+
@vmbuilder.run
|
15
|
+
_start_vm
|
16
|
+
_run_tests
|
17
|
+
@plugman.notify(:task_done, 'tests')
|
18
|
+
end
|
19
|
+
|
20
|
+
def _git_clone
|
21
|
+
return if @os.exists? File.join(@revision.working_dir, '.git')
|
22
|
+
Git.clone @revision.git_url, '.'
|
23
|
+
Git.checkout @revision.branch
|
24
|
+
end
|
25
|
+
|
26
|
+
def _start_vm
|
27
|
+
Vagrant.run "box add --force '#{@revision.complete_box_name}' '#{@revision.complete_box_path}'"
|
28
|
+
Vagrant.use @revision.complete_box_name
|
29
|
+
Vagrant.run "up"
|
30
|
+
end
|
31
|
+
|
32
|
+
def _run_tests
|
33
|
+
Vagrant.run "ssh -c 'cd /vagrant; rake test'"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Vigil
|
2
|
+
class Project
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :working_dir
|
5
|
+
attr_reader :git_url
|
6
|
+
attr_reader :branch
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
@name = args.fetch(:name)
|
10
|
+
@working_dir = File.join(Vigil.run_dir, @name)
|
11
|
+
@os = Vigil.os
|
12
|
+
@git_url = args.fetch(:git_url)
|
13
|
+
@branch = args.fetch(:branch)
|
14
|
+
@revision_repository = RevisionRepository.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_pipeline
|
18
|
+
@os.mkdir_p @working_dir
|
19
|
+
revision = @revision_repository.new
|
20
|
+
revision.run_pipeline
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class Vigil
|
2
|
+
class Revision
|
3
|
+
|
4
|
+
attr_reader :id
|
5
|
+
|
6
|
+
def initialize(id, project)
|
7
|
+
@id = id
|
8
|
+
@project = project
|
9
|
+
@run_dir_boxes = File.join(@project.working_dir, 'boxes')
|
10
|
+
@os = Vigil.os
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_pipeline
|
14
|
+
@os.mkdir_p working_dir
|
15
|
+
@os.mkdir_p @run_dir_boxes
|
16
|
+
Pipeline.new(self).run
|
17
|
+
end
|
18
|
+
|
19
|
+
def previous
|
20
|
+
Revision.new(@id-1, @project)
|
21
|
+
end
|
22
|
+
|
23
|
+
def working_dir
|
24
|
+
File.join(@project.working_dir, @id.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def git_url
|
28
|
+
@project.git_url
|
29
|
+
end
|
30
|
+
|
31
|
+
def sha
|
32
|
+
`bash -c 'GIT_DIR=#{File.join(working_dir, '.git')} git rev-parse HEAD'` #FIXME
|
33
|
+
end
|
34
|
+
|
35
|
+
def branch
|
36
|
+
@project.branch
|
37
|
+
end
|
38
|
+
|
39
|
+
def project_name
|
40
|
+
@project.name
|
41
|
+
end
|
42
|
+
|
43
|
+
def base_box_name
|
44
|
+
"#{@project.name}-#@id"
|
45
|
+
end
|
46
|
+
|
47
|
+
def base_box_path
|
48
|
+
_box_path(base_box_name + '.box')
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_gems_box_name
|
52
|
+
base_box_name + '_no_gems'
|
53
|
+
end
|
54
|
+
|
55
|
+
def no_gems_box_path
|
56
|
+
_box_path(no_gems_box_name + '.pkg')
|
57
|
+
end
|
58
|
+
|
59
|
+
def complete_box_name
|
60
|
+
base_box_name + '_complete'
|
61
|
+
end
|
62
|
+
|
63
|
+
def complete_box_path
|
64
|
+
_box_path(complete_box_name + '.pkg')
|
65
|
+
end
|
66
|
+
|
67
|
+
def _box_path(box)
|
68
|
+
File.join(@run_dir_boxes, box)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Vigil
|
2
|
+
class RevisionRepository
|
3
|
+
|
4
|
+
def initialize(project)
|
5
|
+
@os = Vigil.os
|
6
|
+
@project = project
|
7
|
+
end
|
8
|
+
|
9
|
+
def new
|
10
|
+
Revision.new(most_recent_revision.id+1, @project)
|
11
|
+
end
|
12
|
+
|
13
|
+
def most_recent_revision
|
14
|
+
id = @os.entries(@project.working_dir).select { |f| f =~ /^\d+$/ }.map {|f| f.to_i}.sort.last
|
15
|
+
id ||= 0
|
16
|
+
Revision.new(id, @project)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Vigil
|
2
|
+
class TestPipeline
|
3
|
+
|
4
|
+
def initialize(revision, args={})
|
5
|
+
@revision = revision
|
6
|
+
@plugman = Vigil.plugman
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
@plugman.notify(:build_started)
|
11
|
+
@plugman.notify(:task_started, 'VM1')
|
12
|
+
sleep 5
|
13
|
+
@plugman.notify(:task_done, 'VM1')
|
14
|
+
@plugman.notify(:task_started, 'VM2')
|
15
|
+
sleep 5
|
16
|
+
@plugman.notify(:task_done, 'VM2')
|
17
|
+
@plugman.notify(:task_started, 'VM3')
|
18
|
+
sleep 5
|
19
|
+
@plugman.notify(:task_done, 'VM3')
|
20
|
+
@plugman.notify(:task_started, 'UNIT')
|
21
|
+
sleep 5
|
22
|
+
@plugman.notify(:task_done, 'UNIT')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class Vigil
|
2
|
+
class VMBuilder
|
3
|
+
|
4
|
+
def initialize(revision)
|
5
|
+
@x = Vigil.os
|
6
|
+
@plugman = Vigil.plugman
|
7
|
+
@revision = revision
|
8
|
+
@previous_revision = @revision.previous
|
9
|
+
@rebuild = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
if @x.exists?(@revision.complete_box_path)
|
14
|
+
@plugman.notify(:task_done, 'VM1')
|
15
|
+
@plugman.notify(:task_done, 'VM2')
|
16
|
+
@plugman.notify(:task_done, 'VM3')
|
17
|
+
return
|
18
|
+
end
|
19
|
+
_build_vm
|
20
|
+
end
|
21
|
+
|
22
|
+
def _build_vm
|
23
|
+
_setup_basebox
|
24
|
+
@plugman.notify(:task_done, 'VM1')
|
25
|
+
_setup_no_gems_box
|
26
|
+
@plugman.notify(:task_done, 'VM2')
|
27
|
+
_setup_complete_box
|
28
|
+
@plugman.notify(:task_done, 'VM3')
|
29
|
+
@rebuild = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def _setup_basebox
|
33
|
+
return if @x.exists? @revision.base_box_path
|
34
|
+
if @x.exists?(@previous_revision.base_box_path) and !_changes_relative_to_previous_revision_in?('definitions')
|
35
|
+
_use_old_box(:base_box_path)
|
36
|
+
else
|
37
|
+
_build_basebox
|
38
|
+
@rebuild = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def _build_basebox
|
43
|
+
_setup_iso_cache
|
44
|
+
Vagrant.run "basebox build --force --nogui '#{@revision.project_name}'"
|
45
|
+
Vagrant.run "basebox validate '#{@revision.project_name}'"
|
46
|
+
Vagrant.run "basebox export '#{@revision.project_name}'"
|
47
|
+
@x._system "mv #{@revision.project_name}.box #{@revision.base_box_path}"
|
48
|
+
Vagrant.run "basebox destroy #{@revision.project_name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def _setup_iso_cache
|
52
|
+
@x._system "ln -sf #{File.join(Vigil.run_dir, 'iso')}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def _setup_no_gems_box
|
56
|
+
return if @x.exists?(@revision.no_gems_box_path)
|
57
|
+
if @rebuild or !@x.exists?(@previous_revision.no_gems_box_path) or
|
58
|
+
_changes_relative_to_previous_revision_in?('manifests')
|
59
|
+
_build_no_gems_box
|
60
|
+
@rebuild = true
|
61
|
+
else
|
62
|
+
_use_old_box :no_gems_box_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def _build_no_gems_box
|
67
|
+
Vagrant.run "box add --force '#{@revision.base_box_name}' '#{@revision.base_box_path}'"
|
68
|
+
Vagrant.use @revision.base_box_name
|
69
|
+
Vagrant.run "up"
|
70
|
+
Vagrant.run "package --output #{@revision.no_gems_box_path}"
|
71
|
+
Vagrant.run "box remove #{@revision.base_box_name}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def _setup_complete_box
|
75
|
+
if @rebuild or !@x.exists?(@previous_revision.complete_box_path) or
|
76
|
+
_changes_relative_to_previous_revision_in?('Gemfile*')
|
77
|
+
_build_complete_box
|
78
|
+
else
|
79
|
+
_use_old_box :complete_box_path
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def _build_complete_box
|
84
|
+
Vagrant.run "box add --force '#{@revision.no_gems_box_name}' '#{@revision.no_gems_box_path}'"
|
85
|
+
Vagrant.use @revision.no_gems_box_name
|
86
|
+
Vagrant.run "up"
|
87
|
+
Vagrant.run "ssh -c 'sudo gem install bundler'"
|
88
|
+
Vagrant.run "ssh -c 'cd /vagrant/; bundle install'"
|
89
|
+
Vagrant.run "package --output #{@revision.complete_box_path}"
|
90
|
+
Vagrant.run "box remove '#{@revision.no_gems_box_name}'"
|
91
|
+
end
|
92
|
+
|
93
|
+
def _use_old_box(box)
|
94
|
+
@x.ln @previous_revision.send(box), @revision.send(box)
|
95
|
+
end
|
96
|
+
|
97
|
+
def _changes_relative_to_previous_revision_in?(files)
|
98
|
+
Git.differs?(@previous_revision.sha, files)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Vigil
|
4
|
+
describe Pipeline do
|
5
|
+
|
6
|
+
describe "#run" do
|
7
|
+
it "clones the repository, runs the VMBuilder, starts the VM, and runs tests" do
|
8
|
+
@os = double('os')
|
9
|
+
Vigil.os = @os
|
10
|
+
Vigil.run_dir = "/run"
|
11
|
+
Vigil.plugman = double('plugman').as_null_object
|
12
|
+
@os.should_receive('chdir').with("/run/znork/1").ordered
|
13
|
+
revision = Revision.new(1, Project.new(name: 'znork', os: @os, git_url: '/foo/bar/znork/', branch: 'master'))
|
14
|
+
|
15
|
+
git_clone_expectations
|
16
|
+
start_complete_box_expectations
|
17
|
+
run_tests_expectation
|
18
|
+
vmbuilder = double('vmbuilder')
|
19
|
+
vmbuilder.should_receive('run')
|
20
|
+
Pipeline.new(revision, vmbuilder: vmbuilder).run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def git_clone_expectations
|
25
|
+
@os.should_receive('exists?').with("/run/znork/1/.git").ordered
|
26
|
+
@os.should_receive('_system').with("git clone /foo/bar/znork/ .").ordered
|
27
|
+
@os.should_receive('_system').with("git checkout master").ordered
|
28
|
+
end
|
29
|
+
|
30
|
+
def start_complete_box_expectations
|
31
|
+
@os.should_receive('_system').with("vagrant box add --force 'znork-1_complete' '/run/znork/boxes/znork-1_complete.pkg'").ordered
|
32
|
+
@os.should_receive('_system').with(%Q{ruby -pi -e 'sub(/(config.vm.box = )"[^"]+"/, "\\\\1\\"znork-1_complete\\"")' Vagrantfile}).ordered
|
33
|
+
@os.should_receive('_system').with("vagrant up").ordered
|
34
|
+
end
|
35
|
+
|
36
|
+
def run_tests_expectation
|
37
|
+
@os.should_receive('_system').with("vagrant ssh -c 'cd /vagrant; rake test'").ordered
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Vigil
|
4
|
+
|
5
|
+
describe RevisionRepository do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@os = double('os').as_null_object
|
9
|
+
Vigil.os = @os
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#most_recent_revision" do
|
13
|
+
|
14
|
+
it "returns a Revision with id set to 0 when no revisions are found" do
|
15
|
+
project = double('project', working_dir: '/run_dir')
|
16
|
+
@os.should_receive('entries').with('/run_dir').and_return(%w(boxes))
|
17
|
+
r = RevisionRepository.new(project)
|
18
|
+
r.most_recent_revision.id.should == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
it "finds the revision with the highest ID" do
|
22
|
+
@os.should_receive('entries').with('/run_dir').and_return(%w(boxes 2 1 10 3 6 5 4 7 8 9))
|
23
|
+
project = double('project', working_dir: '/run_dir')
|
24
|
+
r = RevisionRepository.new(project)
|
25
|
+
r.most_recent_revision.id.should == 10
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Vigil
|
4
|
+
|
5
|
+
class Revision
|
6
|
+
def sha; 'the_sha'; end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe VMBuilder do
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
@os = double('os')
|
13
|
+
Vigil.os = @os
|
14
|
+
Vigil.run_dir = "/run"
|
15
|
+
Vigil.plugman = double('plugman').as_null_object
|
16
|
+
end
|
17
|
+
|
18
|
+
after :each do
|
19
|
+
project = Project.new(name: 'znork', os: @os, run_dir: "/run", git_url: '/foo/bar/znork/', branch: 'master')
|
20
|
+
revision = Revision.new(1, project)
|
21
|
+
VMBuilder.new(revision).run
|
22
|
+
end
|
23
|
+
|
24
|
+
context "When the VM has already been built" do
|
25
|
+
it "uses the already built VM" do
|
26
|
+
@os.should_receive('exists?').with("/run/znork/boxes/znork-1_complete.pkg").ordered.and_return(true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "When no VM has been built before" do
|
31
|
+
it "builds a VM from scratch" do
|
32
|
+
@os.stub('exists?', false)
|
33
|
+
basebox_expectations
|
34
|
+
no_gems_box_expectations
|
35
|
+
complete_box_expectations
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "When a VM has been completely built for the previous revision" do
|
40
|
+
before :each do
|
41
|
+
@os.stub('exists?') do |file|
|
42
|
+
%w(/run/znork/boxes/znork-0.box
|
43
|
+
/run/znork/boxes/znork-0_no_gems.pkg
|
44
|
+
/run/znork/boxes/znork-0_complete.pkg).include? file
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "and none of the VM configuration files has changed" do
|
49
|
+
it "reuses the VM" do
|
50
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- definitions").and_return(true)
|
51
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- manifests").and_return(true)
|
52
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- Gemfile*").and_return(true)
|
53
|
+
|
54
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0.box", "/run/znork/boxes/znork-1.box").ordered
|
55
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0_no_gems.pkg", "/run/znork/boxes/znork-1_no_gems.pkg").ordered
|
56
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0_complete.pkg", "/run/znork/boxes/znork-1_complete.pkg").ordered
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "and only the veewee definitions has changed" do
|
61
|
+
it "builds the VM from scratch" do
|
62
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- definitions").and_return(false)
|
63
|
+
basebox_expectations
|
64
|
+
no_gems_box_expectations
|
65
|
+
complete_box_expectations
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "and only the puppet manifests has changed" do
|
70
|
+
it "uses the previous revisions basebox to build the VM" do
|
71
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- definitions").and_return(true)
|
72
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- manifests").and_return(false)
|
73
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0.box", "/run/znork/boxes/znork-1.box").ordered
|
74
|
+
no_gems_box_expectations
|
75
|
+
complete_box_expectations
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "and only Gemfile* has changed" do
|
80
|
+
it "uses the previous revisions basebox to build the VM" do
|
81
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- definitions").and_return(true)
|
82
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- manifests").and_return(true)
|
83
|
+
@os.should_receive('__system').with("git diff --quiet the_sha -- Gemfile*").and_return(false)
|
84
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0.box", "/run/znork/boxes/znork-1.box").ordered
|
85
|
+
@os.should_receive('ln').with("/run/znork/boxes/znork-0_no_gems.pkg", "/run/znork/boxes/znork-1_no_gems.pkg").ordered
|
86
|
+
|
87
|
+
complete_box_expectations
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def basebox_expectations
|
93
|
+
@os.should_receive('_system').with("ln -sf /run/iso").ordered
|
94
|
+
@os.should_receive('_system').with("vagrant basebox build --force --nogui 'znork'").ordered
|
95
|
+
@os.should_receive('_system').with("vagrant basebox validate 'znork'").ordered
|
96
|
+
@os.should_receive('_system').with("vagrant basebox export 'znork'").ordered
|
97
|
+
@os.should_receive('_system').with("mv znork.box /run/znork/boxes/znork-1.box").ordered
|
98
|
+
@os.should_receive('_system').with("vagrant basebox destroy znork").ordered
|
99
|
+
end
|
100
|
+
|
101
|
+
def no_gems_box_expectations
|
102
|
+
@os.should_receive('_system').with("vagrant box add --force 'znork-1' '/run/znork/boxes/znork-1.box'").ordered
|
103
|
+
@os.should_receive('_system').with(%Q{ruby -pi -e 'sub(/(config.vm.box = )"[^"]+"/, "\\\\1\\"znork-1\\"")' Vagrantfile}).ordered
|
104
|
+
@os.should_receive('_system').with("vagrant up").ordered
|
105
|
+
@os.should_receive('_system').with("vagrant package --output /run/znork/boxes/znork-1_no_gems.pkg").ordered
|
106
|
+
@os.should_receive('_system').with("vagrant box remove znork-1").ordered
|
107
|
+
end
|
108
|
+
|
109
|
+
def complete_box_expectations
|
110
|
+
@os.should_receive('_system').with("vagrant box add --force 'znork-1_no_gems' '/run/znork/boxes/znork-1_no_gems.pkg'").ordered
|
111
|
+
@os.should_receive('_system').with(%Q{ruby -pi -e 'sub(/(config.vm.box = )"[^"]+"/, "\\\\1\\"znork-1_no_gems\\"")' Vagrantfile}).ordered
|
112
|
+
@os.should_receive('_system').with("vagrant up").ordered
|
113
|
+
@os.should_receive('_system').with("vagrant ssh -c 'sudo gem install bundler'").ordered
|
114
|
+
@os.should_receive('_system').with("vagrant ssh -c 'cd /vagrant/; bundle install'").ordered
|
115
|
+
@os.should_receive('_system').with("vagrant package --output /run/znork/boxes/znork-1_complete.pkg").ordered
|
116
|
+
@os.should_receive('_system').with("vagrant box remove 'znork-1_no_gems'").ordered
|
117
|
+
end
|
118
|
+
|
119
|
+
def start_complete_box_expectations
|
120
|
+
@os.should_receive('_system').with("vagrant box add --force 'znork-1_complete' '/run/znork/boxes/znork-1_complete.pkg'").ordered
|
121
|
+
@os.should_receive('_system').with(%Q{ruby -pi -e 'sub(/(config.vm.box = )"[^"]+"/, "\\\\1\\"znork-1_complete\\"")' Vagrantfile}).ordered
|
122
|
+
@os.should_receive('_system').with("vagrant up").ordered
|
123
|
+
end
|
124
|
+
|
125
|
+
def run_tests_expectation
|
126
|
+
@os.should_receive('_system').with("vagrant ssh -c 'cd /vagrant; rake test'").ordered
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vigil
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kjell-Magne Øierud
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: vagrant
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: veewee
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: trollop
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: plugman
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: A continous deploy pipeline.
|
79
|
+
email: kjellm@oierud.net
|
80
|
+
executables:
|
81
|
+
- vigil
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- bin/vigil
|
86
|
+
- lib/vigil/git.rb
|
87
|
+
- lib/vigil/os.rb
|
88
|
+
- lib/vigil/pipeline.rb
|
89
|
+
- lib/vigil/project.rb
|
90
|
+
- lib/vigil/revision.rb
|
91
|
+
- lib/vigil/revision_repository.rb
|
92
|
+
- lib/vigil/test_pipeline.rb
|
93
|
+
- lib/vigil/vagrant.rb
|
94
|
+
- lib/vigil/version.rb
|
95
|
+
- lib/vigil/vmbuilder.rb
|
96
|
+
- lib/vigil.rb
|
97
|
+
- spec/lib/vigil/pipeline_spec.rb
|
98
|
+
- spec/lib/vigil/revision_repository_spec.rb
|
99
|
+
- spec/lib/vigil/vmbuilder_spec.rb
|
100
|
+
- spec/lib/vigil_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
- CHANGES
|
103
|
+
- Gemfile
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
homepage: http://github.com/kjellm/vigil
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.9.3
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 1.8.25
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: A continous deploy pipeline.
|
130
|
+
test_files: []
|