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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rubocop.yml +169 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +25 -0
  6. data/Gemfile +10 -0
  7. data/Guardfile +10 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +73 -0
  10. data/Rakefile +13 -0
  11. data/bin/horatio +33 -0
  12. data/horatio.gemspec +30 -0
  13. data/lib/horatio.rb +64 -0
  14. data/lib/horatio/detector.rb +14 -0
  15. data/lib/horatio/detector/docker.rb +39 -0
  16. data/lib/horatio/detector/dynamic.rb +33 -0
  17. data/lib/horatio/detector/io_handler.rb +44 -0
  18. data/lib/horatio/detector/json_reader.rb +15 -0
  19. data/lib/horatio/detector/json_writer.rb +26 -0
  20. data/lib/horatio/detector/maven.rb +48 -0
  21. data/lib/horatio/detector/node_package.rb +30 -0
  22. data/lib/horatio/detector/null_writer.rb +11 -0
  23. data/lib/horatio/detector/rubygem.rb +32 -0
  24. data/lib/horatio/detector/validator.rb +20 -0
  25. data/lib/horatio/helper/vcs.rb +12 -0
  26. data/lib/horatio/releaser.rb +45 -0
  27. data/lib/horatio/vcs.rb +11 -0
  28. data/lib/horatio/vcs/git.rb +41 -0
  29. data/lib/horatio/vcs/subversion.rb +23 -0
  30. data/lib/horatio/version.rb +3 -0
  31. data/spec/fixtures/dynamic +10 -0
  32. data/spec/fixtures/package.json +105 -0
  33. data/spec/fixtures/pom.xml +822 -0
  34. data/spec/fixtures/test.gemspec +32 -0
  35. data/spec/horatio/detector/docker_spec.rb +30 -0
  36. data/spec/horatio/detector/dynamic_spec.rb +19 -0
  37. data/spec/horatio/detector/maven_spec.rb +27 -0
  38. data/spec/horatio/detector/node_package_spec.rb +19 -0
  39. data/spec/horatio/detector/rubygem_spec.rb +28 -0
  40. data/spec/horatio/releaser_spec.rb +25 -0
  41. data/spec/horatio/vcs/git_spec.rb +22 -0
  42. data/spec/horatio/vcs/subversion_spec.rb +15 -0
  43. data/spec/spec_helper.rb +12 -0
  44. data/spec/support/fixture_copy.rb +28 -0
  45. data/spec/support/reporters.rb +3 -0
  46. 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,15 @@
1
+ require 'json'
2
+
3
+ module Horatio
4
+ module Detector
5
+ module JSONReader
6
+ def name
7
+ info['name']
8
+ end
9
+
10
+ def version
11
+ info['version']
12
+ end
13
+ end
14
+ end
15
+ 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,11 @@
1
+ require 'json'
2
+
3
+ module Horatio
4
+ module Detector
5
+ module NULLWritter
6
+ def increment(_release)
7
+ color { Log.info "skipping incrementation of version number, we rely on the #{description} for that" }
8
+ end
9
+ end
10
+ end
11
+ 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,12 @@
1
+ module Horatio
2
+ module Helper
3
+ # Version Control Systems Helper
4
+ module VCS
5
+
6
+ def initialize(options={})
7
+ @options = options
8
+ end
9
+
10
+ end
11
+ end
12
+ 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
@@ -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