builderator 0.3.15 → 1.0.0.pre.rc.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.
- checksums.yaml +4 -4
- data/Gemfile +9 -0
- data/Gemfile.lock +440 -0
- data/README.md +72 -18
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/bin/build-clean +102 -0
- data/bin/build-data +45 -0
- data/builderator.gemspec +7 -4
- data/docs/configuration.md +154 -0
- data/docs/configuration/cookbook.md +19 -0
- data/docs/configuration/profile.md +71 -0
- data/docs/versioning.md +65 -0
- data/lib/builderator.rb +3 -0
- data/lib/builderator/config.rb +93 -0
- data/lib/builderator/config/attributes.rb +287 -0
- data/lib/builderator/config/defaults.rb +163 -0
- data/lib/builderator/config/file.rb +336 -0
- data/lib/builderator/config/rash.rb +80 -0
- data/lib/builderator/control/cleaner.rb +138 -0
- data/lib/builderator/control/cookbook.rb +16 -0
- data/lib/builderator/control/data.rb +16 -0
- data/lib/builderator/control/data/image.rb +98 -0
- data/lib/builderator/control/version.rb +128 -0
- data/lib/builderator/control/version/auto.rb +48 -0
- data/lib/builderator/control/version/bump.rb +82 -0
- data/lib/builderator/control/version/comparable.rb +77 -0
- data/lib/builderator/control/version/git.rb +45 -0
- data/lib/builderator/control/version/scm.rb +92 -0
- data/lib/builderator/interface.rb +67 -0
- data/lib/builderator/interface/berkshelf.rb +38 -0
- data/lib/builderator/interface/packer.rb +75 -0
- data/lib/builderator/interface/vagrant.rb +31 -0
- data/lib/builderator/metadata.rb +5 -3
- data/lib/builderator/model/cleaner.rb +49 -0
- data/lib/builderator/model/cleaner/images.rb +93 -0
- data/lib/builderator/model/cleaner/instances.rb +58 -0
- data/lib/builderator/model/cleaner/launch_configs.rb +47 -0
- data/lib/builderator/model/cleaner/scaling_groups.rb +45 -0
- data/lib/builderator/model/cleaner/snapshots.rb +50 -0
- data/lib/builderator/model/cleaner/volumes.rb +48 -0
- data/lib/builderator/patch/berkshelf.rb +18 -0
- data/lib/builderator/patch/thor-actions.rb +47 -0
- data/lib/builderator/tasks.rb +127 -17
- data/lib/builderator/tasks/berkshelf.rb +63 -0
- data/lib/builderator/tasks/packer.rb +17 -56
- data/lib/builderator/tasks/vagrant.rb +111 -42
- data/lib/builderator/tasks/vendor.rb +94 -0
- data/lib/builderator/tasks/version.rb +58 -0
- data/lib/builderator/util.rb +37 -11
- data/lib/builderator/util/aws_exception.rb +1 -1
- data/lib/builderator/util/limit_exception.rb +12 -11
- data/lib/builderator/util/task_exception.rb +0 -2
- data/mkmf.log +4 -0
- data/spec/config_spec.rb +30 -0
- data/spec/data/Berksfile +6 -0
- data/spec/data/Buildfile +0 -0
- data/spec/data/Vagrantfile +0 -0
- data/spec/data/history.json +483 -0
- data/spec/data/packer.json +0 -0
- data/spec/interface_spec.rb +36 -0
- data/spec/resource/Buildfile +27 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/version_spec.rb +282 -0
- data/template/Berksfile.erb +10 -0
- data/template/Buildfile.erb +28 -0
- data/template/Gemfile.erb +16 -0
- data/template/README.md.erb +61 -0
- data/template/Vagrantfile.erb +75 -0
- data/template/gitignore.erb +104 -0
- data/{.rubocop.yml → template/rubocop.erb} +0 -0
- metadata +203 -56
- data/.gitignore +0 -14
- data/lib/builderator/control/ami.rb +0 -65
- data/lib/builderator/control/clean.rb +0 -130
- data/lib/builderator/model.rb +0 -46
- data/lib/builderator/model/images.rb +0 -89
- data/lib/builderator/model/instances.rb +0 -55
- data/lib/builderator/model/launch_configs.rb +0 -46
- data/lib/builderator/model/scaling_groups.rb +0 -43
- data/lib/builderator/model/snapshots.rb +0 -49
- data/lib/builderator/model/volumes.rb +0 -48
- data/lib/builderator/tasks/ami.rb +0 -47
- data/lib/builderator/tasks/berks.rb +0 -68
- data/lib/builderator/tasks/clean.rb +0 -97
- data/lib/builderator/util/berkshim.rb +0 -34
- data/lib/builderator/util/cookbook.rb +0 -87
- data/lib/builderator/util/packer.rb +0 -39
- data/lib/builderator/util/shell.rb +0 -44
@@ -0,0 +1,48 @@
|
|
1
|
+
module Builderator
|
2
|
+
module Control
|
3
|
+
class Version
|
4
|
+
##
|
5
|
+
# Search through commits since current version for #TYPE tags
|
6
|
+
#
|
7
|
+
# Included in Version
|
8
|
+
##
|
9
|
+
module Auto
|
10
|
+
DEFAULT_TYPE = 'patch'.freeze
|
11
|
+
MESSAGE_KEYWORDS = /#(?<type>build|prerelease|release|patch\-prerelease|patch|minor\-prerelease|minor|major\-prerelease|major)(?:=(?<prerelease>[a-zA-Z0-9\-_]+))?/
|
12
|
+
|
13
|
+
def auto_type
|
14
|
+
fail 'Version-bump type `auto` is unsuppoeted for this SCM. Version does not'\
|
15
|
+
' have a valid `ref` value' if ref.nil?
|
16
|
+
|
17
|
+
## Get commits since self.ref (e.g. commits since this tag)
|
18
|
+
history_since_current = SCM.history.take_while do |commit|
|
19
|
+
commit.id != ref
|
20
|
+
end
|
21
|
+
|
22
|
+
## Search for the highest-precedence #TAG in those commit messages
|
23
|
+
## Search from oldest-to-newest. Newer #TAGs of equal precedence win
|
24
|
+
result = history_since_current.reverse.reduce(nil) do |highest, commit|
|
25
|
+
## Not going to bother parsing multiple matches. If you're
|
26
|
+
## putting more than one #TYPE in your commit message, you
|
27
|
+
## deserve what you get...
|
28
|
+
found_type = commit.message.scan(MESSAGE_KEYWORDS).first
|
29
|
+
|
30
|
+
## No #TYPE in message
|
31
|
+
next highest if found_type.nil?
|
32
|
+
|
33
|
+
## First match
|
34
|
+
next found_type if highest.nil?
|
35
|
+
|
36
|
+
## Retrun higher precedence release type
|
37
|
+
RELEASE_TYPES[found_type.first.to_s] <= RELEASE_TYPES[highest.first.to_s] ? found_type : highest
|
38
|
+
end
|
39
|
+
|
40
|
+
return ['prerelease', nil] if result.nil? && is_prerelease
|
41
|
+
return [DEFAULT_TYPE, nil] if result.nil?
|
42
|
+
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Builderator
|
2
|
+
module Control
|
3
|
+
class Version
|
4
|
+
##
|
5
|
+
# Increment version's parameters by specified steps
|
6
|
+
#
|
7
|
+
# Included in Version
|
8
|
+
##
|
9
|
+
module Bump
|
10
|
+
def bump(type = 'auto', prerelease_name = nil) # rubocop:disable Metrics/PerceivedComplexity
|
11
|
+
## Grok commits since current for a #TYPE string
|
12
|
+
type, prerelease_name = auto_type if type.to_s == 'auto'
|
13
|
+
|
14
|
+
fail "Unrecognized release type #{type}" unless RELEASE_TYPES.include?(type.to_s)
|
15
|
+
type_num = RELEASE_TYPES[type.to_s]
|
16
|
+
|
17
|
+
##
|
18
|
+
# Reset lower-precendence parameters to nil/0
|
19
|
+
##
|
20
|
+
self.build = nil if type_num < RELEASE_TYPES['build']
|
21
|
+
|
22
|
+
## Clear pre-release flags
|
23
|
+
if type_num < RELEASE_TYPES['prerelease']
|
24
|
+
self.is_prerelease = false
|
25
|
+
self.prerelease_name = nil
|
26
|
+
self.prerelease_iteration = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
self.patch = 0 if type_num < RELEASE_TYPES['patch']
|
30
|
+
self.minor = 0 if type_num < RELEASE_TYPES['minor']
|
31
|
+
self.major = 0 if type_num < RELEASE_TYPES['major']
|
32
|
+
|
33
|
+
## Set new version's ref
|
34
|
+
self.ref = SCM.history.first.id
|
35
|
+
|
36
|
+
##
|
37
|
+
# Increment specified parameters
|
38
|
+
##
|
39
|
+
case type.to_s
|
40
|
+
when 'build'
|
41
|
+
if build.nil?
|
42
|
+
self.build = 0
|
43
|
+
else
|
44
|
+
self.build += 1
|
45
|
+
end
|
46
|
+
|
47
|
+
when 'prerelease'
|
48
|
+
## Start a prerelease train from a new patch version
|
49
|
+
## if it doesn't already exist
|
50
|
+
self.patch += 1 unless is_prerelease
|
51
|
+
prerelease(prerelease_name)
|
52
|
+
|
53
|
+
when 'release'
|
54
|
+
## Remove pre-release parameters from the current patch
|
55
|
+
## (already done above ^^)
|
56
|
+
|
57
|
+
when 'patch-prerelease'
|
58
|
+
## Force a new pre-release train from a new patch version
|
59
|
+
self.patch += 1
|
60
|
+
prerelease(prerelease_name)
|
61
|
+
|
62
|
+
when 'patch' then self.patch += 1
|
63
|
+
|
64
|
+
when 'minor-prerelease'
|
65
|
+
self.minor += 1
|
66
|
+
prerelease(prerelease_name)
|
67
|
+
|
68
|
+
when 'minor' then self.minor += 1
|
69
|
+
|
70
|
+
when 'major-prerelease'
|
71
|
+
self.major += 1
|
72
|
+
prerelease(prerelease_name)
|
73
|
+
|
74
|
+
when 'major' then self.major += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
self
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Builderator
|
2
|
+
module Control
|
3
|
+
class Version
|
4
|
+
##
|
5
|
+
# Sort earliest -> latest
|
6
|
+
# (Array.last -> latest (e.g. 1.0.0), Array.first -> earliest(e.g. 0.0.1))
|
7
|
+
##
|
8
|
+
module Comparable
|
9
|
+
include ::Comparable
|
10
|
+
|
11
|
+
def <=>(other)
|
12
|
+
## Simple version comparison
|
13
|
+
return major <=> other.major unless same?(:major, other)
|
14
|
+
return minor <=> other.minor unless same?(:minor, other)
|
15
|
+
return patch <=> other.patch unless same?(:patch, other)
|
16
|
+
|
17
|
+
## Prereleases: prerelease < non-prerelease
|
18
|
+
return compare(:is_prerelease, other) if one?(:is_prerelease, other)
|
19
|
+
|
20
|
+
if both?(:is_prerelease, other)
|
21
|
+
## This is a little sketchy... We're assuming that pre-releases
|
22
|
+
## have a lexicological order.
|
23
|
+
return prerelease_name <=> other.prerelease_name unless same?(:prerelease_name, other)
|
24
|
+
return prerelease_iteration <=> other.prerelease_iteration unless same?(:prerelease_iteration, other)
|
25
|
+
end
|
26
|
+
|
27
|
+
## Build number. With build number > without build number
|
28
|
+
compare(:build, other)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
## this == that
|
34
|
+
def same?(parameter, other)
|
35
|
+
send(parameter) == other.send(parameter)
|
36
|
+
end
|
37
|
+
|
38
|
+
## this && that
|
39
|
+
def both?(parameter, other)
|
40
|
+
send(parameter) && other.send(parameter)
|
41
|
+
end
|
42
|
+
|
43
|
+
## this ^ that (XOR)
|
44
|
+
def one?(parameter, other)
|
45
|
+
(send(parameter)) ^ (other.send(parameter))
|
46
|
+
end
|
47
|
+
|
48
|
+
## this || that
|
49
|
+
def either?(parameter, other)
|
50
|
+
send(parameter) || other.send(parameter)
|
51
|
+
end
|
52
|
+
|
53
|
+
## !(this || that)
|
54
|
+
def neither?(parameter, other)
|
55
|
+
!either?(parameter, other)
|
56
|
+
end
|
57
|
+
|
58
|
+
## Compare with support for `nil` values
|
59
|
+
def compare(parameter, other)
|
60
|
+
a = send(parameter)
|
61
|
+
b = other.send(parameter)
|
62
|
+
|
63
|
+
## NilClass, TrueClass, and FalseClass' <=> operators return nil
|
64
|
+
return a <=> b unless a.nil? || b.nil? ||
|
65
|
+
a.is_a?(TrueClass) || b.is_a?(TrueClass) ||
|
66
|
+
a.is_a?(FalseClass) || b.is_a?(FalseClass)
|
67
|
+
|
68
|
+
return 1 if a && !b
|
69
|
+
return -1 if !a && b
|
70
|
+
|
71
|
+
## a && b || !a && !b
|
72
|
+
0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative './scm'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Control
|
6
|
+
# :nodoc:
|
7
|
+
class Version
|
8
|
+
##
|
9
|
+
# SCM implementation for Git
|
10
|
+
##
|
11
|
+
module Git
|
12
|
+
extend SCM
|
13
|
+
|
14
|
+
COMMIT_FORMAT = /^(?<hash>[a-f0-9]+)(?:\s+\((?<tags>.+?)\))?\s+(?<message>.+)$/
|
15
|
+
TAG_FORMAT = %r{tag: ([a-zA-Z0-9\.\-\+/_]+)}
|
16
|
+
|
17
|
+
## Is there a .git repo in the project root?
|
18
|
+
def self.supported?
|
19
|
+
Util.relative_path('.git').exist?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self._history
|
23
|
+
`git log --pretty='format:%H %d %s' HEAD`.chomp
|
24
|
+
.split("\n")
|
25
|
+
.map { |string| string.match(COMMIT_FORMAT) }
|
26
|
+
.reject(&:nil?)
|
27
|
+
.map do |commit|
|
28
|
+
{
|
29
|
+
:id => commit[:hash],
|
30
|
+
:message => commit[:message]
|
31
|
+
}.tap do |c|
|
32
|
+
tag_match = commit[:tags].scan(TAG_FORMAT)
|
33
|
+
.flatten
|
34
|
+
.reject(&:nil?) unless commit[:tags].nil?
|
35
|
+
|
36
|
+
c[:tags] = tag_match unless tag_match.nil? || tag_match.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
SCM.register(Git)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Builderator
|
2
|
+
module Control
|
3
|
+
class Version
|
4
|
+
##
|
5
|
+
# Generic SCM interface
|
6
|
+
##
|
7
|
+
module SCM
|
8
|
+
## Fetch and cache history for the current HEAD/TIP
|
9
|
+
def history
|
10
|
+
@history ||= _history.map { |commit| Commit.new(commit) }
|
11
|
+
end
|
12
|
+
|
13
|
+
## Find all tags in the branch's history
|
14
|
+
def tags
|
15
|
+
@tags ||= _tags
|
16
|
+
.map { |tag, ref| Version.from_string(tag, :ref => ref) }
|
17
|
+
.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# OVERRIDE: Return true if this provider will work for `path`
|
22
|
+
##
|
23
|
+
def supported?
|
24
|
+
fail 'Method `supported?` must be implemented in SCM providers!'
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# OVERRIDE: Return an array of hashes with keys
|
29
|
+
# - id -> SCM commit identity
|
30
|
+
# - message -> SCM commit message
|
31
|
+
# - tags -> nil or an array of strings
|
32
|
+
##
|
33
|
+
def _history
|
34
|
+
fail 'Method `_history` must be implemented in SCM providers!'
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# OVERRIDE: Return an array of [tag, commit-id] tuples
|
39
|
+
##
|
40
|
+
def _tags
|
41
|
+
history.reject { |commit| commit.tags.empty? }
|
42
|
+
.map { |commit| commit.tags.map { |tag| [tag, commit.id] } }
|
43
|
+
.each_with_object([]) { |commit, tags| tags.push(*commit) }
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def history
|
48
|
+
provider.history
|
49
|
+
end
|
50
|
+
|
51
|
+
def tags
|
52
|
+
provider.tags
|
53
|
+
end
|
54
|
+
|
55
|
+
def register(klass)
|
56
|
+
fail 'Provider module must extend '\
|
57
|
+
'Builderator::Control::Version::SCM' unless
|
58
|
+
klass.singleton_class.include?(SCM)
|
59
|
+
|
60
|
+
## Make newer providers override those with the same capability
|
61
|
+
providers.unshift(klass)
|
62
|
+
end
|
63
|
+
|
64
|
+
def providers
|
65
|
+
@providers ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
## Find a version provider for this build
|
69
|
+
def provider
|
70
|
+
providers.find(&:supported?).tap do |found|
|
71
|
+
fail 'Builderator::Control::Version: '\
|
72
|
+
'Unsupported SCM' if found.nil?
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
## An SCM commit entity
|
78
|
+
class Commit
|
79
|
+
attr_reader :id
|
80
|
+
attr_reader :message
|
81
|
+
attr_reader :tags
|
82
|
+
|
83
|
+
def initialize(match)
|
84
|
+
@id = match[:id]
|
85
|
+
@message = match[:message]
|
86
|
+
@tags = match.fetch(:tags, [])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
require_relative './config/attributes'
|
6
|
+
require_relative './config/rash'
|
7
|
+
require_relative './util'
|
8
|
+
|
9
|
+
module Builderator
|
10
|
+
##
|
11
|
+
# Base class for integration interfaces
|
12
|
+
##
|
13
|
+
class Interface
|
14
|
+
class << self
|
15
|
+
def command(arg = nil)
|
16
|
+
@command = arg unless arg.nil?
|
17
|
+
@command
|
18
|
+
end
|
19
|
+
|
20
|
+
def from_gem(arg = nil)
|
21
|
+
@from_gem = arg unless arg.nil?
|
22
|
+
@from_gem || @command
|
23
|
+
end
|
24
|
+
|
25
|
+
def template(arg = nil)
|
26
|
+
@template = arg unless arg.nil?
|
27
|
+
@template
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
## Is vagrant in this bundle?
|
32
|
+
def bundled?
|
33
|
+
Gem.loaded_specs.key?(self.class.from_gem)
|
34
|
+
end
|
35
|
+
|
36
|
+
def which
|
37
|
+
return self.class.command if bundled?
|
38
|
+
|
39
|
+
## Not in the bundle. Use system path
|
40
|
+
`which #{self.class.command}`.chomp.tap { |path| fail "Unable to locate a #{self.class.command} executable" if path.empty? }
|
41
|
+
end
|
42
|
+
alias_method :command, :which
|
43
|
+
|
44
|
+
def directory
|
45
|
+
Util.workspace
|
46
|
+
end
|
47
|
+
|
48
|
+
def render
|
49
|
+
ERB.new(Util.source_path(self.class.template).binread,
|
50
|
+
nil, '-', '@output_buffer').result(Config.instance_eval('binding'))
|
51
|
+
end
|
52
|
+
|
53
|
+
def source
|
54
|
+
fail 'Interface does not provide a source!'
|
55
|
+
end
|
56
|
+
|
57
|
+
def write
|
58
|
+
directory.mkpath
|
59
|
+
source.write(render)
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def clean
|
64
|
+
source.unlink
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative '../interface'
|
2
|
+
require_relative '../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
# :nodoc:
|
6
|
+
class Interface
|
7
|
+
class << self
|
8
|
+
def berkshelf
|
9
|
+
@berkshelf ||= Berkshelf.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Render an updated Berksfile
|
15
|
+
##
|
16
|
+
class Berkshelf < Interface
|
17
|
+
from_gem 'berkshelf'
|
18
|
+
command 'berks'
|
19
|
+
template 'template/Berksfile.erb'
|
20
|
+
|
21
|
+
def vendor
|
22
|
+
Config.local.cookbook_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def lockfile
|
26
|
+
Util.workspace('Berksfile.lock')
|
27
|
+
end
|
28
|
+
|
29
|
+
def berkshelf_config
|
30
|
+
Config.cookbook.berkshelf_config
|
31
|
+
end
|
32
|
+
|
33
|
+
def source
|
34
|
+
directory.join('Berksfile')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|