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,28 @@
1
+ require 'evrone/common/amqp'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ class BuildsConsumer
7
+
8
+ include Evrone::Common::AMQP::Consumer
9
+
10
+ exchange 'ci.builds'
11
+ queue 'ci.worker.builds.generic'
12
+ ack true
13
+
14
+ model Message::PerformBuild
15
+
16
+ def perform(message)
17
+ build = Build.new message
18
+ number = Thread.current[:consumer_id] || 0
19
+ path_prefix = "/tmp/.test/build.#{number}"
20
+
21
+ Router.new(build, path_prefix).perform
22
+ ack!
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ require 'evrone/common/amqp'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ class JobsConsumer
7
+
8
+ include Evrone::Common::AMQP::Consumer
9
+
10
+ exchange 'ci.jobs'
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def extract_options!
3
+ self.last.is_a?(Hash) ? self.pop : {}
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def compact
3
+ gsub(/\n/, ' ').gsub(/ +/, ' ').strip
4
+ end
5
+
6
+ def camelize
7
+ split("_").each {|s| s.capitalize! }.join("")
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Helper::Config
5
+
6
+ def config
7
+ Router.config
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Helper::Logger
5
+
6
+ def logger
7
+ Router.logger
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+
5
+ module Helper::TraceShCommand
6
+ def trace_sh_command(cmd, options = {})
7
+ trace = options[:trace] || cmd
8
+ "echo #{Shellwords.escape "$ #{trace}"}\n#{cmd}"
9
+ end
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ require 'evrone/common/amqp'
2
+
3
+ module Evrone::CI::Router::AMQP
4
+
5
+ Base = Struct.new("Subscribing", :app) do
6
+ include Evrone::CI::Router::Helper::Logger
7
+
8
+ def consumer_name
9
+ Thread.current[:consumer_name]
10
+ end
11
+
12
+ def consumer_id
13
+ Thread.current[:consumer_id]
14
+ end
15
+
16
+ def consumer_tag
17
+ consumer_id ? "#{consumer_name.split('::').last} #{consumer_id}" : consumer_name
18
+ end
19
+ end
20
+
21
+ class Subscribing < Base
22
+ def call(env)
23
+ logger.tagged(consumer_tag) do
24
+ logger.warn "subsribing #{env[:exchange].name}"
25
+ rs = app.call env
26
+ logger.warn "shutdown"
27
+ rs
28
+ end
29
+ end
30
+ end
31
+
32
+ class Recieving < Base
33
+ def call(env)
34
+ logger.warn "payload recieved #{env[:payload].inspect[0...60]}..."
35
+ rs = app.call env
36
+ logger.warn "commit message"
37
+ rs
38
+ end
39
+ end
40
+
41
+ class Publishing < Base
42
+ def call(env)
43
+ app.call env
44
+ end
45
+ end
46
+ end
47
+
48
+ Evrone::Common::AMQP.configure do |c|
49
+ c.subscribing do
50
+ use Evrone::CI::Router::AMQP::Subscribing
51
+ end
52
+
53
+ c.recieving do
54
+ use Evrone::CI::Router::AMQP::Recieving
55
+ end
56
+
57
+ c.publishing do
58
+ use Evrone::CI::Router::AMQP::Publishing
59
+ end
60
+
61
+ c.content_type = 'application/x-protobuf'
62
+ c.logger = nil
63
+ end
@@ -0,0 +1,54 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Middleware
5
+
6
+ CreateBuildMatrix = Struct.new(:app) do
7
+
8
+ include Helper::Logger
9
+
10
+ def call(env)
11
+ if create_build_matrix_and_delivery(env)
12
+ app.call env
13
+ else
14
+ -1
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def create_build_matrix_and_delivery(env)
21
+ source_travis = load_travis(env.repo_dir)
22
+ if source_travis
23
+ matrix = Router::BuildMatrix.new source_travis
24
+ update_build env.build, matrix
25
+
26
+ matrix.travises.each_with_index do |travis, idx|
27
+ delivery_job env.build, travis, idx+1
28
+ end
29
+ true
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ def delivery_job(build, travis, number)
36
+ message = build.to_perform_job_message travis, number
37
+ logger.info "delivery job #{message.id}.#{number} #{travis.to_matrix_s}"
38
+ Router::JobsConsumer.publish message
39
+ end
40
+
41
+ def update_build(build, matrix)
42
+ build.matrix = matrix.keys
43
+ build.jobs_count = matrix.travises.size
44
+ end
45
+
46
+ def load_travis(repo_dir)
47
+ Router::Travis.from_file repo_dir.join(".travis.yml")
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ require 'evrone/ci/common'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ module Middleware
7
+
8
+ CreateDirs = Struct.new(:app) do
9
+
10
+ include Common::Helper::Shell
11
+ include Helper::Config
12
+
13
+ def call(env)
14
+ env.repo_dir = env.path_prefix.join(config.repo_dir_name)
15
+ mkdir env.repo_dir
16
+
17
+ app.call env
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,22 @@
1
+ require 'evrone/ci/common'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ module Middleware
7
+
8
+ FetchCommitInfo = Struct.new(:app) do
9
+
10
+ def call(env)
11
+ if env.scm
12
+ env.build.commit_info = env.scm.commit_info
13
+ end
14
+ app.call env
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,36 @@
1
+ require 'evrone/ci/common'
2
+
3
+ module Evrone
4
+ module CI
5
+ class Router
6
+ module Middleware
7
+
8
+ FetchSource = Struct.new(:app) do
9
+
10
+ include Helper::Logger
11
+
12
+ def call(env)
13
+ env.scm = create_scm(env)
14
+ if env.scm.fetch == 0
15
+ app.call env
16
+ else
17
+ -1
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def create_scm(env)
24
+ SCM::Git.new(env.build.message.src,
25
+ env.build.message.sha,
26
+ env.repo_dir,
27
+ deploy_key: env.build.message.deploy_key,
28
+ &env.build.method(:add_to_output))
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,24 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Middleware
5
+
6
+ LogBuild = Struct.new(:app) do
7
+
8
+ include Router::Helper::Logger
9
+
10
+ def call(env)
11
+ logger.tagged("BUILD #{env.build.message.id}") do
12
+ logger.info "starting build"
13
+ rs = app.call env
14
+ logger.info "done build"
15
+ rs
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,21 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Middleware::Travis
5
+
6
+ Env = Struct.new(:app) do
7
+
8
+ include Helper::TraceShCommand
9
+
10
+ def call(env)
11
+ env.init << 'export LC_ALL=en_US.UTF8'
12
+ env.before_install << trace_sh_command("env")
13
+ app.call(env)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,55 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Middleware::Travis
5
+
6
+ Ruby = Struct.new(:app) do
7
+
8
+ include Helper::TraceShCommand
9
+
10
+ def call(env)
11
+ if rvm env
12
+ env.init.tap do |i|
13
+ i << 'eval "$(rbenv init -)" || true'
14
+ i << "rbenv shell #{make_rbenv_version_command env}"
15
+ i << 'export BUNDLE_GEMFILE=${PWD}/Gemfile'
16
+ i << 'export GEM_HOME=/tmp/.rubygems'
17
+ end
18
+
19
+ env.before_install.tap do |b|
20
+ b << "gem query -q -in '^bundler$' > /dev/null || gem install bundler -q --no-rdoc --no-ri"
21
+ b << trace_sh_command("ruby --version")
22
+ b << trace_sh_command("gem --version")
23
+ b << trace_sh_command("bundle --version")
24
+ end
25
+
26
+ env.install.tap do |i|
27
+ i << trace_sh_command("bundle install")
28
+ end
29
+ end
30
+
31
+ app.call(env)
32
+ end
33
+
34
+ private
35
+
36
+ def rvm(env)
37
+ env.travis.rvm.last
38
+ end
39
+
40
+ def make_rbenv_version_command(env)
41
+ %{
42
+ $(rbenv versions |
43
+ sed -e 's/^\*/ /' |
44
+ awk '{print $1}' |
45
+ grep -v 'system' |
46
+ grep '#{rvm env}' |
47
+ tail -n1)
48
+ }.compact
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ module Evrone
2
+ module CI
3
+ class Router
4
+ module Middleware::Travis
5
+
6
+ Script = Struct.new(:app) do
7
+
8
+ include Helper::TraceShCommand
9
+
10
+ def call(env)
11
+ env.travis.before_script.each do |c|
12
+ env.before_script << trace_sh_command(c)
13
+ end
14
+ env.travis.script.each do |c|
15
+ env.script << trace_sh_command(c)
16
+ end
17
+ app.call(env)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+