vigil 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/kjellm/vigil.png)](http://travis-ci.org/kjellm/vigil)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/kjellm/vigil.png)](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: []
|