horatio 0.1.7
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 +7 -0
- data/.gitignore +24 -0
- data/.rubocop.yml +169 -0
- data/.ruby-version +1 -0
- data/.travis.yml +25 -0
- data/Gemfile +10 -0
- data/Guardfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +13 -0
- data/bin/horatio +33 -0
- data/horatio.gemspec +30 -0
- data/lib/horatio.rb +64 -0
- data/lib/horatio/detector.rb +14 -0
- data/lib/horatio/detector/docker.rb +39 -0
- data/lib/horatio/detector/dynamic.rb +33 -0
- data/lib/horatio/detector/io_handler.rb +44 -0
- data/lib/horatio/detector/json_reader.rb +15 -0
- data/lib/horatio/detector/json_writer.rb +26 -0
- data/lib/horatio/detector/maven.rb +48 -0
- data/lib/horatio/detector/node_package.rb +30 -0
- data/lib/horatio/detector/null_writer.rb +11 -0
- data/lib/horatio/detector/rubygem.rb +32 -0
- data/lib/horatio/detector/validator.rb +20 -0
- data/lib/horatio/helper/vcs.rb +12 -0
- data/lib/horatio/releaser.rb +45 -0
- data/lib/horatio/vcs.rb +11 -0
- data/lib/horatio/vcs/git.rb +41 -0
- data/lib/horatio/vcs/subversion.rb +23 -0
- data/lib/horatio/version.rb +3 -0
- data/spec/fixtures/dynamic +10 -0
- data/spec/fixtures/package.json +105 -0
- data/spec/fixtures/pom.xml +822 -0
- data/spec/fixtures/test.gemspec +32 -0
- data/spec/horatio/detector/docker_spec.rb +30 -0
- data/spec/horatio/detector/dynamic_spec.rb +19 -0
- data/spec/horatio/detector/maven_spec.rb +27 -0
- data/spec/horatio/detector/node_package_spec.rb +19 -0
- data/spec/horatio/detector/rubygem_spec.rb +28 -0
- data/spec/horatio/releaser_spec.rb +25 -0
- data/spec/horatio/vcs/git_spec.rb +22 -0
- data/spec/horatio/vcs/subversion_spec.rb +15 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/fixture_copy.rb +28 -0
- data/spec/support/reporters.rb +3 -0
- metadata +232 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require "horatio/detector/docker"
|
2
|
+
require "horatio/detector/rubygem"
|
3
|
+
require "horatio/detector/maven"
|
4
|
+
require "horatio/detector/node_package"
|
5
|
+
require "horatio/detector/dynamic"
|
6
|
+
|
7
|
+
module Horatio
|
8
|
+
module Detector
|
9
|
+
def self.detect
|
10
|
+
detected = [Dynamic, Docker, Maven, RubyGem, NodePackage].detect { |d| d.detect }
|
11
|
+
detected ? detected.new : raise("couldn't detect a supported project type, takes docker, maven, gem, horatio")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'horatio/detector/validator'
|
4
|
+
require 'horatio/detector/json_reader'
|
5
|
+
require 'horatio/detector/json_writer'
|
6
|
+
require 'horatio/detector/io_handler'
|
7
|
+
|
8
|
+
module Horatio
|
9
|
+
module Detector
|
10
|
+
class Docker
|
11
|
+
include Validator
|
12
|
+
include IOHandler
|
13
|
+
include JSONReader
|
14
|
+
include JSONWriter
|
15
|
+
|
16
|
+
def default_input
|
17
|
+
'horatio.json'
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_output
|
21
|
+
'horatio.json'
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_commit
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def info
|
29
|
+
memo_read do
|
30
|
+
JSON.parse(File.open(input, 'r').read)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def description
|
35
|
+
'horatio.json'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'horatio/detector/validator'
|
4
|
+
require 'horatio/detector/json_reader'
|
5
|
+
require 'horatio/detector/io_handler'
|
6
|
+
require 'horatio/detector/null_writer'
|
7
|
+
|
8
|
+
module Horatio
|
9
|
+
module Detector
|
10
|
+
class Dynamic
|
11
|
+
include Validator
|
12
|
+
include IOHandler
|
13
|
+
include JSONReader
|
14
|
+
include NULLWritter
|
15
|
+
|
16
|
+
def default_input
|
17
|
+
'horatio'
|
18
|
+
end
|
19
|
+
|
20
|
+
def info
|
21
|
+
memo_read do
|
22
|
+
out = `./#{input}`
|
23
|
+
raise StandardError, "dynamic horatio exec failed: #{out}" unless out
|
24
|
+
JSON.parse(out)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def description
|
29
|
+
'dynamic Horatio data generator'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Horatio
|
2
|
+
module Detector
|
3
|
+
module IOHandler
|
4
|
+
module ClassMethods
|
5
|
+
def detect
|
6
|
+
new.detect
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :input, :output
|
11
|
+
|
12
|
+
def default_input
|
13
|
+
'horatio.json'
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_output
|
17
|
+
'horatio.json'
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(input: nil, output: nil)
|
21
|
+
@input = input || default_input
|
22
|
+
@output = output || default_output
|
23
|
+
@info = {}
|
24
|
+
@read = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def detect
|
28
|
+
File.exists?(@input) ? true : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def memo_read
|
32
|
+
return @info if @read
|
33
|
+
return unless block_given?
|
34
|
+
@info = yield
|
35
|
+
@read = true
|
36
|
+
@info
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.included(base)
|
40
|
+
base.extend(ClassMethods)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Horatio
|
4
|
+
module Detector
|
5
|
+
module JSONWriter
|
6
|
+
def increment(releaser)
|
7
|
+
increment_version
|
8
|
+
if ENV['DRY_RUN']
|
9
|
+
color { Log.info "dry run: would've saved updated #{output}" }
|
10
|
+
return
|
11
|
+
end
|
12
|
+
color { Log.info "saving updated #{output}" }
|
13
|
+
File.open(output, 'w') { |f| f.write(JSON.pretty_generate(info)) } unless ENV['DRY_RUN']
|
14
|
+
releaser.vcs.commit(output)
|
15
|
+
end
|
16
|
+
|
17
|
+
def increment_version
|
18
|
+
parts = info['version'].split('.')
|
19
|
+
parts[-1] = parts[-1].to_i + 1
|
20
|
+
version = parts.join('.')
|
21
|
+
color { Log.info "incrementing version from #{info['version']} to #{version}"}
|
22
|
+
info['version'] = version
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'nori'
|
2
|
+
|
3
|
+
require 'horatio/detector/validator'
|
4
|
+
require 'horatio/detector/io_handler'
|
5
|
+
require 'horatio/detector/null_writer'
|
6
|
+
|
7
|
+
module Horatio
|
8
|
+
module Detector
|
9
|
+
class Maven
|
10
|
+
include Validator
|
11
|
+
include IOHandler
|
12
|
+
|
13
|
+
def default_input
|
14
|
+
'pom.xml'
|
15
|
+
end
|
16
|
+
|
17
|
+
def info
|
18
|
+
memo_read do
|
19
|
+
File.open('pom.xml', 'r') { |f| Nori.new.parse(f.read) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
info['project']['artifactId']
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Maven version reader
|
29
|
+
#
|
30
|
+
# We need to decrease the number if we see SNAPSHOT, this is becasue
|
31
|
+
# maven increments it in anticipation for the next build
|
32
|
+
#
|
33
|
+
def version
|
34
|
+
version = info['project']['version'] || info['project']['parent']['version']
|
35
|
+
return version unless version =~ /-SNAPSHOT$/
|
36
|
+
version = version.split('-')[0]
|
37
|
+
version = version.split('.')
|
38
|
+
minor = version.last.to_i > 1 ? version.last.to_i - 1 : version.last
|
39
|
+
version[-1] = minor
|
40
|
+
version.join('.')
|
41
|
+
end
|
42
|
+
|
43
|
+
def description
|
44
|
+
'JAVA Maven pom.xml'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'horatio/detector/validator'
|
4
|
+
require 'horatio/detector/json_reader'
|
5
|
+
require 'horatio/detector/null_writer'
|
6
|
+
|
7
|
+
module Horatio
|
8
|
+
module Detector
|
9
|
+
class NodePackage
|
10
|
+
include Validator
|
11
|
+
include IOHandler
|
12
|
+
include JSONReader
|
13
|
+
include NULLWritter
|
14
|
+
|
15
|
+
def default_input
|
16
|
+
'package.json'
|
17
|
+
end
|
18
|
+
|
19
|
+
def info
|
20
|
+
memo_read do
|
21
|
+
File.open(input, 'r') { |f| JSON.parse(f.read) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
'Node.js package.json'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'horatio/detector/validator'
|
2
|
+
require 'horatio/detector/null_writer'
|
3
|
+
|
4
|
+
module Horatio
|
5
|
+
module Detector
|
6
|
+
class RubyGem
|
7
|
+
include Validator
|
8
|
+
include NULLWritter
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
File.open(Dir.glob('*.gemspec').first, 'r') { |f| @spec_file = f.read }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.detect
|
15
|
+
Dir.glob('*.gemspec').any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def name
|
19
|
+
@spec_file.match(/spec\.name.*$/i).to_s.split('=')[1].strip.gsub(/[\'\"\\]/, '')
|
20
|
+
end
|
21
|
+
|
22
|
+
def version
|
23
|
+
File.open(Dir.glob('lib/**/version.rb').first, 'rb') { |f| @version_file = f.read }
|
24
|
+
@version_file.match(/(\d.)+\d/).to_s.strip.gsub(/[\'\"\\]/, '')
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
'Ruby gemspec'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Horatio
|
2
|
+
module Detector
|
3
|
+
module Validator
|
4
|
+
def validate_name
|
5
|
+
color { Log.info "validating passed in name"}
|
6
|
+
name.match(/^[\w\-\.]*$/i) ? true : raise("name specified using invalid format")
|
7
|
+
end
|
8
|
+
|
9
|
+
def validate_version
|
10
|
+
color { Log.info "validating passed in version"}
|
11
|
+
version.match(/^(\d+.)+\d+/i) ? true : raise("version specified using invalid format")
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate
|
15
|
+
validate_version
|
16
|
+
validate_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Horatio
|
4
|
+
class Releaser
|
5
|
+
|
6
|
+
attr_accessor :release, :vcs
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
@options = options
|
10
|
+
@registry = @options['registry']
|
11
|
+
@release = Horatio::Detector.detect
|
12
|
+
color { Log.info "detected #{@release.description}" }
|
13
|
+
@vcs = Horatio::VCS.detect(@options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_artifact
|
17
|
+
contents = JSON.pretty_generate({'name' => @release.name,
|
18
|
+
'version' => "#{@release.version}-#{@vcs.latest_revision}",
|
19
|
+
'app_version' => @release.version,
|
20
|
+
'source_revision' => @vcs.latest_revision,
|
21
|
+
'url' => "#{@registry}/#{@release.name}:#{@release.version}-#{@vcs.latest_revision}"})
|
22
|
+
|
23
|
+
File.open('docker-image.json', 'w') { |f | f.write(contents); }
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
color { Log.info "Running Docker build for #{@release.name}-#{@release.version}" }
|
28
|
+
|
29
|
+
@release.validate
|
30
|
+
|
31
|
+
color { Log.info "latest revision is #{@vcs.latest_revision }" }
|
32
|
+
|
33
|
+
no_cache = ENV['DOCKER_BUILD_NO_CACHE'] ? "--no-cache " : ""
|
34
|
+
|
35
|
+
run_sh "docker build " + no_cache + "-t #{@registry}/#{@release.name}:#{@release.version}-#{@vcs.latest_revision} ."
|
36
|
+
run_sh "docker push #{@registry}/#{@release.name}"
|
37
|
+
|
38
|
+
generate_artifact
|
39
|
+
|
40
|
+
@release.increment(self)
|
41
|
+
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/horatio/vcs.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'horatio/vcs/git'
|
2
|
+
require 'horatio/vcs/subversion'
|
3
|
+
|
4
|
+
module Horatio
|
5
|
+
module VCS
|
6
|
+
def self.detect(options={})
|
7
|
+
vcs = [Git, Subversion].detect { |d| d.detect }
|
8
|
+
vcs ? vcs.new(options) : abort('No VCS detected (git/subversion)')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "horatio/helper/vcs"
|
3
|
+
|
4
|
+
module Horatio
|
5
|
+
module VCS
|
6
|
+
class Git
|
7
|
+
|
8
|
+
include Horatio::Helper::VCS
|
9
|
+
|
10
|
+
def self.detect
|
11
|
+
sh('git rev-parse HEAD').last.exitstatus == 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def latest_revision
|
15
|
+
sh('git rev-parse --short HEAD').first.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
def commit(file)
|
19
|
+
color { Log.info "Adding remote before pushing verion update: #{remote_url}" }
|
20
|
+
sh "git remote rm horatio &> /dev/null"
|
21
|
+
run_sh "git remote add horatio #{remote_url}"
|
22
|
+
run_sh "git commit -m 'image release' #{file}"
|
23
|
+
run_sh "git push horatio master"
|
24
|
+
end
|
25
|
+
|
26
|
+
def remote_url
|
27
|
+
begin
|
28
|
+
url = @options.fetch('git-repo-url')
|
29
|
+
rescue => e
|
30
|
+
color(ERROR) { Log.error "Since Horatio 1.0 you must specify a remote repo URL when building a docker only / horatio build" }
|
31
|
+
color(ERROR) { Log.error "If you see this message update your build to look like the following example: 'horatio --git-repo-url http://github.com/test/test.git'" }
|
32
|
+
|
33
|
+
raise e
|
34
|
+
end
|
35
|
+
|
36
|
+
url
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'horatio/helper/vcs'
|
2
|
+
|
3
|
+
module Horatio
|
4
|
+
module VCS
|
5
|
+
class Subversion
|
6
|
+
|
7
|
+
include Horatio::Helper::VCS
|
8
|
+
|
9
|
+
def self.detect
|
10
|
+
['.svn', '.subversion'].any? { |f| File.exist?(f) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def latest_revision
|
14
|
+
sh('svnversion').first.strip.split(':')[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
def commit(file)
|
18
|
+
run_sh "svn commit -m 'image release' #{file}"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|