evrone-ci-router 0.2.0.pre0

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +7 -0
  5. data/README.md +1 -0
  6. data/Rakefile +22 -0
  7. data/bin/cli +3 -0
  8. data/bin/git_ssh +3 -0
  9. data/bin/jobs_publisher +12 -0
  10. data/bin/workers +13 -0
  11. data/evrone-ci-router.gemspec +30 -0
  12. data/fixtures/travis.yml +5 -0
  13. data/lib/evrone/ci/router.rb +100 -0
  14. data/lib/evrone/ci/router/build.rb +60 -0
  15. data/lib/evrone/ci/router/build_matrix.rb +89 -0
  16. data/lib/evrone/ci/router/configuration.rb +27 -0
  17. data/lib/evrone/ci/router/consumers/build_logs_consumer.rb +15 -0
  18. data/lib/evrone/ci/router/consumers/build_status_consumer.rb +15 -0
  19. data/lib/evrone/ci/router/consumers/builds_consumer.rb +28 -0
  20. data/lib/evrone/ci/router/consumers/jobs_consumer.rb +15 -0
  21. data/lib/evrone/ci/router/ext/array.rb +5 -0
  22. data/lib/evrone/ci/router/ext/string.rb +9 -0
  23. data/lib/evrone/ci/router/helper/config.rb +13 -0
  24. data/lib/evrone/ci/router/helper/logger.rb +13 -0
  25. data/lib/evrone/ci/router/helper/trace_sh_command.rb +14 -0
  26. data/lib/evrone/ci/router/initializers/amqp.rb +63 -0
  27. data/lib/evrone/ci/router/middleware/create_build_matrix.rb +54 -0
  28. data/lib/evrone/ci/router/middleware/create_dirs.rb +25 -0
  29. data/lib/evrone/ci/router/middleware/fetch_commit_info.rb +22 -0
  30. data/lib/evrone/ci/router/middleware/fetch_source.rb +36 -0
  31. data/lib/evrone/ci/router/middleware/log_build.rb +24 -0
  32. data/lib/evrone/ci/router/middleware/travis/env.rb +21 -0
  33. data/lib/evrone/ci/router/middleware/travis/ruby.rb +55 -0
  34. data/lib/evrone/ci/router/middleware/travis/script.rb +25 -0
  35. data/lib/evrone/ci/router/middleware/update_build_status.rb +75 -0
  36. data/lib/evrone/ci/router/queue.rb +58 -0
  37. data/lib/evrone/ci/router/travis.rb +104 -0
  38. data/lib/evrone/ci/router/travis/serializable.rb +45 -0
  39. data/lib/evrone/ci/router/version.rb +7 -0
  40. data/spec/lib/build_matrix_spec.rb +145 -0
  41. data/spec/lib/build_spec.rb +75 -0
  42. data/spec/lib/configuration_spec.rb +22 -0
  43. data/spec/lib/middleware/create_build_matrix_spec.rb +73 -0
  44. data/spec/lib/middleware/create_dirs_spec.rb +26 -0
  45. data/spec/lib/middleware/fetch_commit_info_spec.rb +23 -0
  46. data/spec/lib/middleware/fetch_source_spec.rb +27 -0
  47. data/spec/lib/middleware/log_build_spec.rb +14 -0
  48. data/spec/lib/middleware/update_build_status_spec.rb +70 -0
  49. data/spec/lib/queue_spec.rb +55 -0
  50. data/spec/lib/travis_spec.rb +182 -0
  51. data/spec/spec_helper.rb +17 -0
  52. data/spec/support/create.rb +47 -0
  53. data/spec/support/fixture.rb +7 -0
  54. data/spec/support/shared_examples/update_build_status_message.rb +5 -0
  55. metadata +228 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bfbf13a7842e030d4d20aa825df0c5aede860177
4
+ data.tar.gz: da99904e2ddeacee3c87c9b9c56a63e6981dd860
5
+ SHA512:
6
+ metadata.gz: d645737756afe9953e85d2054fe436dff8b3dd8b5e7aa209d9f023e2f732c114809db6ded81b28a5f708c7f71405791b69cbdccf3574934e3ee9ff599be9f5e5
7
+ data.tar.gz: 9cc5c15fb61e8ffb93809e24c6a979f5218bfca721fceb676456c2b1e6a44831759b38b5ea2359a75753cc773af41ec776ead1df21e9130822376bde7245e3a4
@@ -0,0 +1,7 @@
1
+ fixtures/repo
2
+ .test
3
+ .vagrant
4
+ .bundle
5
+ pkg/
6
+ fixtures/repo
7
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ -f d
2
+ --color
3
+ --order=rand
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in evrone-ci-job.gemspec
4
+ gemspec
5
+ gem 'evrone-ci-common', path: File.expand_path("../../common", __FILE__)
6
+ gem 'evrone-ci-message', path: File.expand_path("../../message", __FILE__)
7
+
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require
4
+ require 'rspec/core/rake_task'
5
+ require "bundler/gem_tasks"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => ["test:create_repo", :spec]
10
+
11
+ namespace :test do
12
+ task :create_repo do
13
+ dir = "fixtures/repo"
14
+ unless File.directory? dir
15
+ cmd = "git clone https://github.com/evrone/ci-worker-test-repo.git fixtures/repo"
16
+ puts cmd
17
+ system cmd
18
+ end
19
+ end
20
+ end
21
+
22
+ task :travis => :default
data/bin/cli ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ bundle exec pry -r$(pwd)/lib/evrone/ci/worker.rb
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ exec /usr/bin/ssh -A -o StrictHostKeyChecking=no "$@"
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../../lib/evrone/ci/router", __FILE__)
4
+
5
+ require File.expand_path("../../spec/support/fixture", __FILE__)
6
+ require File.expand_path("../../spec/support/create", __FILE__)
7
+
8
+ require 'evrone/ci/message/testing'
9
+
10
+ include Evrone::CI
11
+
12
+ Router::BuildsConsumer.publish Message::PerformBuild.test_message
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../../lib/evrone/ci/router", __FILE__)
4
+
5
+ trap('INT') {
6
+ Thread.new do
7
+ Evrone::Common::AMQP.shutdown
8
+ end.join
9
+ }
10
+
11
+ Evrone::Common::AMQP::Supervisor::Threaded.build(
12
+ Evrone::CI::Router::BuildsConsumer => 1,
13
+ ).run
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require File.expand_path('../lib/evrone/ci/router/version.rb', __FILE__)
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "evrone-ci-router"
8
+ spec.version = Evrone::CI::Router::VERSION
9
+ spec.authors = ["Dmitry Galinsky"]
10
+ spec.email = ["dima.exe@gmail.com"]
11
+ spec.description = %q{ ci router }
12
+ spec.summary = %q{ ci router }
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency 'evrone-ci-common', "= #{Evrone::CI::Router::VERSION}"
22
+ spec.add_runtime_dependency 'evrone-ci-message', "= #{Evrone::CI::Router::VERSION}"
23
+ spec.add_runtime_dependency 'evrone-common-amqp', '~> 0.1.1'
24
+ spec.add_runtime_dependency 'hashr', '= 0.0.22'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rspec"
29
+ spec.add_development_dependency "rr"
30
+ end
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 2.0.0
3
+ before_script:
4
+ - "echo before_script"
5
+ script: "RAILS_ENV=test ls -1 && echo DONE!"
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require :default
4
+
5
+ require 'pathname'
6
+
7
+ require File.expand_path("../..", __FILE__) + "/ci/router/ext/string.rb"
8
+ require File.expand_path("../..", __FILE__) + "/ci/router/ext/array.rb"
9
+
10
+ module Evrone
11
+ module CI
12
+ class Router
13
+
14
+ autoload :Configuration, File.expand_path("../router/configuration", __FILE__)
15
+ autoload :Build, File.expand_path("../router/build", __FILE__)
16
+ autoload :BuildMatrix, File.expand_path("../router/build_matrix", __FILE__)
17
+ autoload :Queue, File.expand_path("../router/queue", __FILE__)
18
+ autoload :Travis, File.expand_path("../router/travis", __FILE__)
19
+
20
+ autoload :BuildLogsConsumer, File.expand_path("../router/consumers/build_logs_consumer", __FILE__)
21
+ autoload :BuildStatusConsumer, File.expand_path("../router/consumers/build_status_consumer", __FILE__)
22
+ autoload :BuildsConsumer, File.expand_path("../router/consumers/builds_consumer", __FILE__)
23
+ autoload :JobsConsumer, File.expand_path("../router/consumers/jobs_consumer", __FILE__)
24
+
25
+ module Helper
26
+ autoload :Config, File.expand_path("../router/helper/config", __FILE__)
27
+ autoload :Logger, File.expand_path("../router/helper/logger", __FILE__)
28
+ autoload :TraceShCommand, File.expand_path("../router/helper/trace_sh_command", __FILE__)
29
+ end
30
+
31
+ module Middleware
32
+ module Travis
33
+ autoload :Env, File.expand_path("../router/middleware/travis/env", __FILE__)
34
+ autoload :Ruby, File.expand_path("../router/middleware/travis/ruby", __FILE__)
35
+ autoload :Script, File.expand_path("../router/middleware/travis/script", __FILE__)
36
+ end
37
+ autoload :CreateBuildMatrix, File.expand_path("../router/middleware/create_build_matrix", __FILE__)
38
+ autoload :FetchSource, File.expand_path("../router/middleware/fetch_source", __FILE__)
39
+ autoload :FetchCommitInfo, File.expand_path("../router/middleware/fetch_commit_info", __FILE__)
40
+ autoload :LogBuild, File.expand_path("../router/middleware/log_build", __FILE__)
41
+ autoload :UpdateBuildStatus, File.expand_path("../router/middleware/update_build_status", __FILE__)
42
+ autoload :CreateDirs, File.expand_path("../router/middleware/create_dirs", __FILE__)
43
+ end
44
+
45
+ @@root = Pathname.new File.expand_path('../../../..', __FILE__)
46
+ @@config = Configuration.new
47
+
48
+ class << self
49
+ def root
50
+ @@root
51
+ end
52
+
53
+ def logger
54
+ config.logger
55
+ end
56
+
57
+ def configure
58
+ yield config
59
+ config
60
+ end
61
+
62
+ def config
63
+ @@config
64
+ end
65
+
66
+ def reset_config!
67
+ @@config = Configuration.new
68
+ end
69
+ end
70
+
71
+ include Common::Helper::Middlewares
72
+
73
+ middlewares do
74
+ use Middleware::LogBuild
75
+ use Middleware::UpdateBuildStatus
76
+ use Middleware::CreateDirs
77
+ use Middleware::FetchSource
78
+ use Middleware::FetchCommitInfo
79
+ use Middleware::CreateBuildMatrix
80
+ end
81
+
82
+ attr_reader :build, :path_prefix
83
+
84
+ def initialize(build, path_prefix)
85
+ @build = build
86
+ @path_prefix = Pathname.new(path_prefix).expand_path
87
+ end
88
+
89
+ def perform
90
+ env = OpenStruct.new build: build, path_prefix: path_prefix
91
+ run_middlewares(env) { |_| 0 }
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+
98
+ Evrone::CI::Router.root.join("lib/evrone/ci/router/initializers").children.each do |e|
99
+ require e
100
+ end
@@ -0,0 +1,60 @@
1
+ require 'evrone/ci/message'
2
+ require 'evrone/ci/common'
3
+
4
+ module Evrone
5
+ module CI
6
+ class Router
7
+ class Build
8
+
9
+ include Router::Helper::Logger
10
+ include Router::Helper::Config
11
+
12
+ attr_reader :message, :output
13
+ attr_accessor :matrix, :jobs_count, :commit_info
14
+
15
+ def initialize(perform_build_message)
16
+ @output = ''
17
+ @message = perform_build_message
18
+ end
19
+
20
+ def to_perform_job_message(travis, job_id)
21
+ queue = travis.to_queue
22
+ job_message = Message::PerformJob.new(
23
+ id: message.id,
24
+ name: message.name,
25
+ src: message.src,
26
+ sha: message.sha,
27
+ pull_request_id: message.pull_request_id,
28
+ deploy_key: message.deploy_key,
29
+ job_id: job_id,
30
+ before_script: queue.to_before_script,
31
+ script: queue.to_script,
32
+ matrix_keys: travis.matrix_keys,
33
+ )
34
+ job_message
35
+ end
36
+
37
+ def add_to_output(str)
38
+ output << str
39
+ logger.debug str.strip if logger.level == 0
40
+ BuildLogsConsumer.publish create_build_log_message(str)
41
+ end
42
+
43
+ def add_command_to_output(cmd)
44
+ add_to_output "$ #{cmd}\n"
45
+ end
46
+
47
+ def create_build_log_message(data)
48
+ tm = Time.now
49
+ Message::BuildLog.new(
50
+ build_id: message.id,
51
+ tm: tm.to_i,
52
+ tm_usec: tm.usec,
53
+ log: data
54
+ )
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,89 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ class BuildMatrix
5
+
6
+ KEYS = (Travis::LANGS + %w{ env }).freeze
7
+
8
+ attr_reader :travis
9
+
10
+ def initialize(travis)
11
+ @travis = travis
12
+ end
13
+
14
+ def keys
15
+ extract_pair_of_key_and_values.map(&:first).sort
16
+ end
17
+
18
+ def travises
19
+ attributes_for_new_travises.map do |attrs|
20
+ Travis.new attrs
21
+ end
22
+ end
23
+
24
+ def attributes_for_new_travises
25
+ permutate_and_build_values.inject([]) do |ac, values|
26
+ ac << values.inject({}) do |a,val|
27
+ a[val.key] = val.value
28
+ a
29
+ end
30
+ ac
31
+ end
32
+ end
33
+
34
+ def permutate_and_build_values
35
+ values = extract_pair_of_key_and_values.map do |key, vals|
36
+ vals.map{|it| Value.new(key, it) }
37
+ end
38
+ if matrix_values?(values)
39
+ array_permutations(values).map do |it|
40
+ if it.is_a?(Array)
41
+ it.flatten
42
+ else
43
+ [it]
44
+ end
45
+ end
46
+ else
47
+ values
48
+ end.sort_by(&:to_s)
49
+ end
50
+
51
+ def extract_pair_of_key_and_values
52
+ KEYS.map.inject([]) do |a, k|
53
+ if (val = travis[k]) && !val.empty?
54
+ a << [k, val]
55
+ end
56
+ a
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def matrix_values?(values)
63
+ !values.all?{|i| i.size == 1 }
64
+ end
65
+
66
+ def array_permutations array, index=0
67
+ # index is 0 by default : start at the beginning, more elegant.
68
+ return array[-1] if index == array.size - 1 # Return last element if at end.
69
+
70
+ result = []
71
+
72
+ array[index].each do |element| # For each array
73
+ array_permutations(array, index + 1).each do |x| # Permute permute permute
74
+ result << [element, x]
75
+ end
76
+ end
77
+ result
78
+ end
79
+
80
+ Value = Struct.new(:key, :value) do
81
+ def to_s
82
+ [key, value].join(":")
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ require 'hashr'
2
+ require 'logger'
3
+ require 'evrone/ci/common/tagged_logging'
4
+
5
+ module Evrone
6
+ module CI
7
+ class Router
8
+ class Configuration < ::Hashr
9
+
10
+ extend Hashr::EnvDefaults
11
+
12
+ self.env_namespace = 'ci_router'
13
+ self.raise_missing_keys = true
14
+
15
+ define amqp_url: nil,
16
+ timeout: 30 * 60,
17
+ logger: Common::TaggedLogging.new(Logger.new STDOUT),
18
+ repo_dir_name: "repo"
19
+
20
+ def timeout
21
+ self[:timeout].to_i
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'evrone/common/amqp'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ class BuildLogsConsumer
7
+
8
+ include Evrone::Common::AMQP::Consumer
9
+
10
+ exchange 'ci.builds.log'
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'evrone/common/amqp'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ class BuildStatusConsumer
7
+
8
+ include Evrone::Common::AMQP::Consumer
9
+
10
+ exchange 'ci.builds.status'
11
+
12
+ end
13
+ end
14
+ end
15
+ end