vx-router 0.2.0.pre28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +9 -0
  5. data/LICENSE.txt +276 -0
  6. data/Rakefile +46 -0
  7. data/bin/vx-router +5 -0
  8. data/fixtures/jobs_publisher +13 -0
  9. data/fixtures/travis.yml +5 -0
  10. data/lib/vx/router.rb +158 -0
  11. data/lib/vx/router/build.rb +80 -0
  12. data/lib/vx/router/cli.rb +53 -0
  13. data/lib/vx/router/configuration.rb +27 -0
  14. data/lib/vx/router/consumers/build_logs_consumer.rb +13 -0
  15. data/lib/vx/router/consumers/build_status_consumer.rb +13 -0
  16. data/lib/vx/router/consumers/builds_consumer.rb +27 -0
  17. data/lib/vx/router/consumers/job_status_consumer.rb +13 -0
  18. data/lib/vx/router/consumers/jobs_consumer.rb +13 -0
  19. data/lib/vx/router/ext/array.rb +5 -0
  20. data/lib/vx/router/ext/string.rb +9 -0
  21. data/lib/vx/router/helper/config.rb +11 -0
  22. data/lib/vx/router/helper/logger.rb +11 -0
  23. data/lib/vx/router/helper/trace_sh_command.rb +12 -0
  24. data/lib/vx/router/initializers/amqp.rb +3 -0
  25. data/lib/vx/router/script_builder.rb +98 -0
  26. data/lib/vx/router/script_builder/databases.rb +28 -0
  27. data/lib/vx/router/script_builder/env.rb +21 -0
  28. data/lib/vx/router/script_builder/prepare.rb +58 -0
  29. data/lib/vx/router/script_builder/ruby.rb +68 -0
  30. data/lib/vx/router/script_builder/script.rb +22 -0
  31. data/lib/vx/router/script_builder/webdav_cache.rb +80 -0
  32. data/lib/vx/router/version.rb +5 -0
  33. data/spec/lib/build_spec.rb +123 -0
  34. data/spec/lib/configuration_spec.rb +23 -0
  35. data/spec/lib/router_spec.rb +80 -0
  36. data/spec/lib/script_builder/prepare_spec.rb +44 -0
  37. data/spec/lib/script_builder/webdav_cache_spec.rb +80 -0
  38. data/spec/lib/script_builder_spec.rb +36 -0
  39. data/spec/spec_helper.rb +17 -0
  40. data/spec/support/create.rb +40 -0
  41. data/spec/support/fixture.rb +7 -0
  42. data/spec/support/last_build_log_message.rb +3 -0
  43. data/spec/support/shared_examples/update_build_status_message.rb +5 -0
  44. data/vx-router.gemspec +32 -0
  45. metadata +225 -0
@@ -0,0 +1,58 @@
1
+ require 'vx/common'
2
+
3
+ module Vx
4
+ class Router
5
+ class ScriptBuilder
6
+
7
+ Prepare = Struct.new(:app) do
8
+
9
+ include Helper::TraceShCommand
10
+ include Common::Helper::UploadShCommand
11
+
12
+ def call(env)
13
+ name = env.build.message.name
14
+ deploy_key = env.build.message.deploy_key
15
+
16
+ repo_path = "code/#{name}"
17
+ data_path = "data/#{name}"
18
+ key_file = "#{data_path}/key"
19
+ git_ssh_file = "#{data_path}/git_ssh"
20
+
21
+ sha = env.build.message.sha
22
+ scm = build_scm(env, sha, repo_path)
23
+ git_ssh = scm.git_ssh.class.template(deploy_key && "$PWD/#{key_file}")
24
+
25
+ env.init.tap do |i|
26
+ i << "mkdir -p #{data_path}"
27
+ i << "mkdir -p #{repo_path}"
28
+
29
+ if deploy_key
30
+ i << "echo instaling keys"
31
+ i << upload_sh_command(key_file, deploy_key)
32
+ i << "chmod 0600 #{key_file}"
33
+ end
34
+
35
+ i << upload_sh_command(git_ssh_file, git_ssh)
36
+ i << "chmod 0750 #{git_ssh_file}"
37
+
38
+ i << "export GIT_SSH=$PWD/#{git_ssh_file}"
39
+ i << scm.make_fetch_command
40
+ i << "unset GIT_SSH"
41
+ end
42
+
43
+ app.call env
44
+ end
45
+
46
+ private
47
+
48
+ def build_scm(env, sha, path)
49
+ SCM::Git.new(env.build.message.src,
50
+ sha,
51
+ "$PWD/#{path}",
52
+ branch: env.build.message.branch)
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,68 @@
1
+ module Vx
2
+ class Router
3
+ class ScriptBuilder
4
+
5
+ Ruby = Struct.new(:app) do
6
+
7
+ ALIASES = {
8
+ '1.8.7' => "system"
9
+ }
10
+
11
+ include Helper::TraceShCommand
12
+
13
+ def call(env)
14
+ if rvm env
15
+ env.cache_key << "rvm-#{rvm env}"
16
+
17
+ env.before_install.tap do |i|
18
+ i << 'eval "$(rbenv init -)" || true'
19
+ i << "rbenv shell #{make_rbenv_version_command env}"
20
+ i << 'export BUNDLE_GEMFILE=${PWD}/Gemfile'
21
+ i << 'export GEM_HOME=$HOME/cached/rubygems'
22
+ end
23
+
24
+ env.announce.tap do |a|
25
+ a << trace_sh_command("ruby --version")
26
+ a << trace_sh_command("gem --version")
27
+ a << trace_sh_command("bundle --version")
28
+ end
29
+
30
+ env.install.tap do |i|
31
+ i << trace_sh_command("bundle install")
32
+ i << trace_sh_command("bundle clean --force")
33
+ end
34
+ end
35
+
36
+ app.call(env)
37
+ end
38
+
39
+ private
40
+
41
+ def rvm(env)
42
+ env.configuration.rvm.first
43
+ end
44
+
45
+ def make_rbenv_version_command(env)
46
+ select_rbenv_version_by_aliases(env) ||
47
+ select_rbenv_version(env)
48
+ end
49
+
50
+ def select_rbenv_version_by_aliases(env)
51
+ ALIASES[rvm(env)]
52
+ end
53
+
54
+ def select_rbenv_version(env)
55
+ %{
56
+ $(rbenv versions |
57
+ sed -e 's/^\*/ /' |
58
+ awk '{print $1}' |
59
+ grep -v 'system' |
60
+ grep '#{rvm env}' |
61
+ tail -n1)
62
+ }.compact
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,22 @@
1
+ module Vx
2
+ class Router
3
+ class ScriptBuilder
4
+
5
+ Script = Struct.new(:app) do
6
+
7
+ include Helper::TraceShCommand
8
+
9
+ def call(env)
10
+ env.configuration.before_script.each do |c|
11
+ env.before_script << trace_sh_command(c)
12
+ end
13
+ env.configuration.script.each do |c|
14
+ env.script << trace_sh_command(c)
15
+ end
16
+ app.call(env)
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,80 @@
1
+ module Vx
2
+ class Router
3
+ class ScriptBuilder
4
+
5
+ WebdavCache = Struct.new(:app) do
6
+
7
+ include Helper::Config
8
+ include Helper::Logger
9
+
10
+ CASHER_URL = "https://raw.github.com/travis-ci/casher/production/bin/casher"
11
+ CASHER_BIN = "$HOME/.casher/bin/casher"
12
+
13
+ def call(env)
14
+ rs = app.call env
15
+
16
+ if config.webdav_cache_url
17
+ assign_url_to_env(env)
18
+ prepare(env)
19
+ fetch(env)
20
+ add(env)
21
+ push(env)
22
+ end
23
+
24
+ rs
25
+ end
26
+
27
+ private
28
+
29
+ def assign_url_to_env(env)
30
+ urls = []
31
+ branch = env.build.message.branch
32
+ if branch != 'master'
33
+ urls << url_for(env, branch)
34
+ end
35
+ puts urls.inspect
36
+ urls << url_for(env, 'master')
37
+
38
+ env.webdav_fetch_url = urls
39
+ env.webdav_push_url = url_for(env, branch)
40
+ env
41
+ end
42
+
43
+ def url_for(env, branch)
44
+ name = env.build.message.name.dup + "/" + branch
45
+
46
+ key = env.cache_key.join("-").gsub(/[^a-z0-9_\-.]/, '-')
47
+ "#{config.webdav_cache_url}/#{name}/#{key}.tgz"
48
+ end
49
+
50
+ def prepare(env)
51
+ cmd = %{
52
+ export CASHER_DIR=$HOME/.casher &&
53
+ ( mkdir -p $CASHER_DIR/bin &&
54
+ curl #{CASHER_URL} -s -o #{CASHER_BIN} &&
55
+ chmod +x #{CASHER_BIN} ) ||
56
+ true
57
+ }.compact
58
+ env.init << cmd
59
+ end
60
+
61
+ def fetch(env)
62
+ urls = env.webdav_fetch_url.join(" ")
63
+ env.init << "#{CASHER_BIN} fetch #{urls} || true"
64
+ end
65
+
66
+ def add(env)
67
+ env.init << "#{CASHER_BIN} add $HOME/cached || true"
68
+ env.init << "unset CASHER_DIR"
69
+ end
70
+
71
+ def push(env)
72
+ if env.webdav_push_url
73
+ env.after_script << "#{CASHER_BIN} push #{env.webdav_push_url}"
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,5 @@
1
+ module Vx
2
+ class Router
3
+ VERSION = "0.2.0.pre28"
4
+ end
5
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+ require 'vx/common'
3
+
4
+ describe Vx::Router::Build do
5
+ let(:msg) { create :message, 'PerformBuild' }
6
+ let(:build) { described_class.new msg }
7
+
8
+ subject { build }
9
+
10
+ context "just created" do
11
+ its(:message) { should eq msg }
12
+ its(:output) { should be_an_instance_of(Vx::Common::OutputBuffer)}
13
+ its(:output_counter) { should eq 0 }
14
+ end
15
+
16
+ context "publish_build_log_message" do
17
+ let(:data) { 'log' }
18
+ subject { build.publish_build_log_message data }
19
+
20
+ it { should be_an_instance_of(Vx::Message::BuildLog) }
21
+ its(:build_id) { should eq build.message.id }
22
+ its(:tm) { should eq 1 }
23
+ its(:log) { should eq data }
24
+
25
+ it "should increment counter" do
26
+ expect {
27
+ subject
28
+ }.to change(build, :output_counter).by(1)
29
+ end
30
+
31
+ it "should delivery message" do
32
+ expect {
33
+ subject
34
+ }.to change(Vx::Router::BuildLogsConsumer.messages, :count).by(1)
35
+ expect(last_build_log_message.log).to eq data
36
+ end
37
+ end
38
+
39
+ context "to_build_status_message" do
40
+ subject { build.to_build_status_message Vx::Router::Build::STARTED }
41
+
42
+ before do
43
+ build.jobs_count = 1
44
+ end
45
+
46
+ it { should be_an_instance_of(Vx::Message::BuildStatus) }
47
+ its(:build_id) { should eq build.message.id }
48
+ its(:status) { should eq 2 }
49
+ its(:tm) { should be }
50
+ its(:jobs_count) { should eq 1 }
51
+ end
52
+
53
+ context "add_to_output" do
54
+ let(:data) { 'data' }
55
+ let(:messages) { Vx::Router::BuildLogsConsumer.messages }
56
+ subject do
57
+ build.add_to_output(data)
58
+ build.output.flush
59
+ build
60
+ end
61
+
62
+ it "should delivery message" do
63
+ expect {
64
+ subject
65
+ }.to change(messages, :size).by(1)
66
+ expect(last_build_log_message.log).to eq data
67
+ end
68
+
69
+ it "should increment output_counter" do
70
+ expect {
71
+ subject
72
+ }.to change(build, :output_counter).by(1)
73
+ expect(last_build_log_message.tm).to eq 1
74
+ end
75
+ end
76
+
77
+ context "add_command_to_output" do
78
+ let(:data) { 'data' }
79
+ let(:messages) { Vx::Router::BuildLogsConsumer.messages }
80
+ subject do
81
+ build.add_command_to_output(data)
82
+ build.output.flush
83
+ build
84
+ end
85
+
86
+ it "should delivery message" do
87
+ expect {
88
+ subject
89
+ }.to change(messages, :size).by(1)
90
+ expect(last_build_log_message.log).to eq "$ #{data}\n"
91
+ end
92
+
93
+ it "should increment output_counter" do
94
+ expect {
95
+ subject
96
+ }.to change(build, :output_counter).by(1)
97
+ expect(last_build_log_message.tm).to eq 1
98
+ end
99
+ end
100
+
101
+ context ".to_perform_job_message" do
102
+ let(:config) { create :configuration }
103
+ let(:job_id) { 2 }
104
+ subject { build.to_perform_job_message config, job_id }
105
+
106
+ it { should be_an_instance_of Vx::Message::PerformJob }
107
+
108
+ context "created message" do
109
+ its(:id) { should eq build.message.id }
110
+ its(:name) { should eq build.message.name }
111
+ its(:job_id) { should eq job_id }
112
+ its(:before_script) { should be }
113
+ its(:script) { should be }
114
+ its(:after_script) { should be }
115
+ its(:matrix_keys) { should eq ['rvm:2.0.0'] }
116
+ end
117
+ end
118
+
119
+ context "scm_class" do
120
+ subject { build.scm_class }
121
+ it { should eq Vx::SCM::Git }
122
+ end
123
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vx::Router::Configuration do
4
+ let(:config) { Vx::Router.config }
5
+ subject { config }
6
+
7
+ before { Vx::Router.reset_config! }
8
+
9
+ its(:timeout) { should eq 1800 }
10
+ its(:amqp_url) { should be_nil }
11
+
12
+ context ".configure" do
13
+ subject {
14
+ Vx::Router.configure do |c|
15
+ c.timeout = 1
16
+ c.amqp_url = "2"
17
+ end
18
+ }
19
+ its(:timeout) { should eq 1 }
20
+ its(:amqp_url) { should eq "2" }
21
+ its(:workers) { should eq 1 }
22
+ end
23
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+
5
+ describe Vx::Router do
6
+ let(:build) { create :build }
7
+ let(:router) { described_class.new build }
8
+ subject { router }
9
+
10
+ context "just created" do
11
+ its(:build) { should eq build }
12
+ end
13
+
14
+ context "#perform" do
15
+ subject { router.perform }
16
+ it { should be_true }
17
+ end
18
+
19
+ context "#update_build_status" do
20
+ let(:messages) { Vx::Router::BuildStatusConsumer.messages }
21
+ let(:first_message) { messages.first }
22
+ let(:last_message) { messages.last }
23
+
24
+ it "should delivery STARTED and FINISHED when success" do
25
+ router.update_build_status { true }
26
+ expect(messages).to have(2).items
27
+ expect(first_message.status).to eq Vx::Router::Build::STARTED
28
+ expect(last_message.status).to eq Vx::Router::Build::FINISHED
29
+ end
30
+
31
+ it "should delivery STARTED and FAILED when failed" do
32
+ router.update_build_status { false }
33
+ expect(messages).to have(2).items
34
+ expect(first_message.status).to eq Vx::Router::Build::STARTED
35
+ expect(last_message.status).to eq Vx::Router::Build::FAILED
36
+ end
37
+
38
+ it "should delivery STARTED and FAILED when exception raised" do
39
+ router.update_build_status { raise "Ignore Me" }
40
+ expect(messages).to have(2).items
41
+ expect(first_message.status).to eq Vx::Router::Build::STARTED
42
+ expect(last_message.status).to eq Vx::Router::Build::FAILED
43
+ end
44
+ end
45
+
46
+ context "#load_configuration" do
47
+ subject { router.load_configuration }
48
+
49
+ it "should build new BuildConfiguration instance from message" do
50
+ expect(subject).to be_true
51
+ expect(router.configuration).to be
52
+ end
53
+ end
54
+
55
+ context "#create_and_delivery_build_matrix" do
56
+ let(:messages) { Vx::Router::JobsConsumer.messages }
57
+ let(:message) { messages.first }
58
+ subject { router.create_and_delivery_build_matrix }
59
+ before do
60
+ stub(router).configuration { create :configuration }
61
+ end
62
+
63
+ it "should create build matrix from source configuration and delivery its to jobs" do
64
+ expect(subject).to be_true
65
+ expect(messages).to have(1).item
66
+ expect(message.job_id).to eq 1
67
+ end
68
+
69
+ it "should publish job_status message with status = INITIALIZED" do
70
+ expect {
71
+ subject
72
+ }.to change(Vx::Router::JobStatusConsumer.messages, :count).by(1)
73
+ message = Vx::Router::JobStatusConsumer.messages.last
74
+ expect(message.build_id).to eq build.message.id
75
+ expect(message.job_id).to eq 1
76
+ expect(message.status).to eq 0
77
+ end
78
+ end
79
+
80
+ end