vx-router 0.2.0.pre28
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 +7 -0
- data/.rspec +3 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +276 -0
- data/Rakefile +46 -0
- data/bin/vx-router +5 -0
- data/fixtures/jobs_publisher +13 -0
- data/fixtures/travis.yml +5 -0
- data/lib/vx/router.rb +158 -0
- data/lib/vx/router/build.rb +80 -0
- data/lib/vx/router/cli.rb +53 -0
- data/lib/vx/router/configuration.rb +27 -0
- data/lib/vx/router/consumers/build_logs_consumer.rb +13 -0
- data/lib/vx/router/consumers/build_status_consumer.rb +13 -0
- data/lib/vx/router/consumers/builds_consumer.rb +27 -0
- data/lib/vx/router/consumers/job_status_consumer.rb +13 -0
- data/lib/vx/router/consumers/jobs_consumer.rb +13 -0
- data/lib/vx/router/ext/array.rb +5 -0
- data/lib/vx/router/ext/string.rb +9 -0
- data/lib/vx/router/helper/config.rb +11 -0
- data/lib/vx/router/helper/logger.rb +11 -0
- data/lib/vx/router/helper/trace_sh_command.rb +12 -0
- data/lib/vx/router/initializers/amqp.rb +3 -0
- data/lib/vx/router/script_builder.rb +98 -0
- data/lib/vx/router/script_builder/databases.rb +28 -0
- data/lib/vx/router/script_builder/env.rb +21 -0
- data/lib/vx/router/script_builder/prepare.rb +58 -0
- data/lib/vx/router/script_builder/ruby.rb +68 -0
- data/lib/vx/router/script_builder/script.rb +22 -0
- data/lib/vx/router/script_builder/webdav_cache.rb +80 -0
- data/lib/vx/router/version.rb +5 -0
- data/spec/lib/build_spec.rb +123 -0
- data/spec/lib/configuration_spec.rb +23 -0
- data/spec/lib/router_spec.rb +80 -0
- data/spec/lib/script_builder/prepare_spec.rb +44 -0
- data/spec/lib/script_builder/webdav_cache_spec.rb +80 -0
- data/spec/lib/script_builder_spec.rb +36 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/create.rb +40 -0
- data/spec/support/fixture.rb +7 -0
- data/spec/support/last_build_log_message.rb +3 -0
- data/spec/support/shared_examples/update_build_status_message.rb +5 -0
- data/vx-router.gemspec +32 -0
- metadata +225 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'vx/message'
|
2
|
+
require 'vx/common'
|
3
|
+
|
4
|
+
module Vx
|
5
|
+
class Router
|
6
|
+
class Build
|
7
|
+
|
8
|
+
INITIALIED = 0
|
9
|
+
STARTED = 2
|
10
|
+
FINISHED = 3
|
11
|
+
FAILED = 5
|
12
|
+
|
13
|
+
include Router::Helper::Logger
|
14
|
+
include Router::Helper::Config
|
15
|
+
|
16
|
+
attr_reader :message, :output, :output_counter
|
17
|
+
attr_accessor :jobs_count
|
18
|
+
|
19
|
+
def initialize(perform_build_message)
|
20
|
+
@output_counter = 0
|
21
|
+
@output = Common::OutputBuffer.new(&method(:publish_build_log_message))
|
22
|
+
@message = perform_build_message
|
23
|
+
end
|
24
|
+
|
25
|
+
def release
|
26
|
+
output.close
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_perform_job_message(configuration, job_id)
|
30
|
+
script_builder = ScriptBuilder.new self, configuration
|
31
|
+
job_message = Message::PerformJob.new(
|
32
|
+
id: message.id,
|
33
|
+
name: message.name,
|
34
|
+
job_id: job_id,
|
35
|
+
before_script: script_builder.to_before_script,
|
36
|
+
script: script_builder.to_script,
|
37
|
+
after_script: script_builder.to_after_script,
|
38
|
+
matrix_keys: configuration.matrix_keys,
|
39
|
+
)
|
40
|
+
job_message
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_build_status_message(status)
|
44
|
+
tm = Time.now
|
45
|
+
attributes = {
|
46
|
+
build_id: message.id,
|
47
|
+
status: status,
|
48
|
+
tm: tm.to_i,
|
49
|
+
jobs_count: jobs_count || 0,
|
50
|
+
}
|
51
|
+
Message::BuildStatus.new attributes
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_to_output(str)
|
55
|
+
output << str
|
56
|
+
logger.debug str.strip if logger.level == 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_command_to_output(cmd)
|
60
|
+
add_to_output "$ #{cmd}\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
def publish_build_log_message(str)
|
64
|
+
@output_counter += 1
|
65
|
+
log = Message::BuildLog.new(
|
66
|
+
build_id: message.id,
|
67
|
+
tm: output_counter,
|
68
|
+
log: str
|
69
|
+
)
|
70
|
+
BuildLogsConsumer.publish log
|
71
|
+
log
|
72
|
+
end
|
73
|
+
|
74
|
+
def scm_class
|
75
|
+
Vx::SCM::Git
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'vx/common/amqp_setup'
|
3
|
+
require 'vx/common/env_file'
|
4
|
+
|
5
|
+
module Vx
|
6
|
+
class Router
|
7
|
+
class CLI
|
8
|
+
|
9
|
+
include Helper::Config
|
10
|
+
include Helper::Logger
|
11
|
+
include Common::EnvFile
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@options = {}
|
15
|
+
parse!
|
16
|
+
Router.initialize!
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
trap('INT') {
|
21
|
+
Thread.new do
|
22
|
+
Vx::Common::AMQP.shutdown
|
23
|
+
end.join
|
24
|
+
}
|
25
|
+
|
26
|
+
Vx::Common::AMQP::Supervisor::Threaded.build(
|
27
|
+
Vx::Router::BuildsConsumer => config.workers,
|
28
|
+
).run
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse!
|
34
|
+
OptionParser.new do |opts|
|
35
|
+
opts.banner = "Usage: vx-router [options]"
|
36
|
+
opts.on("-w", "--workers NUM", "Number of workers, default 1") do |v|
|
37
|
+
@options[:workers] = v.to_i
|
38
|
+
end
|
39
|
+
opts.on("-c", "--config FILE", "Path to configuration file, default /etc/vexor/ci") do |v|
|
40
|
+
@options[:config] = v
|
41
|
+
end
|
42
|
+
end.parse!
|
43
|
+
|
44
|
+
read_env_file @options.delete(:config)
|
45
|
+
|
46
|
+
@options.each_pair do |k,v|
|
47
|
+
config.public_send("#{k}=", v)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'hashr'
|
2
|
+
require 'logger'
|
3
|
+
require 'vx/common/tagged_logging'
|
4
|
+
|
5
|
+
module Vx
|
6
|
+
class Router
|
7
|
+
class Configuration < ::Hashr
|
8
|
+
|
9
|
+
extend Hashr::EnvDefaults
|
10
|
+
|
11
|
+
self.env_namespace = 'ci_router'
|
12
|
+
self.raise_missing_keys = true
|
13
|
+
|
14
|
+
define amqp_url: nil,
|
15
|
+
timeout: 30 * 60,
|
16
|
+
logger: Common::TaggedLogging.new(Logger.new STDOUT),
|
17
|
+
workers: 1,
|
18
|
+
webdav_cache_url: nil
|
19
|
+
|
20
|
+
|
21
|
+
def timeout
|
22
|
+
self[:timeout].to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'vx/common/amqp'
|
2
|
+
require 'vx/message'
|
3
|
+
|
4
|
+
module Vx
|
5
|
+
class Router
|
6
|
+
class BuildsConsumer
|
7
|
+
|
8
|
+
include Vx::Common::AMQP::Consumer
|
9
|
+
include Helper::Logger
|
10
|
+
|
11
|
+
exchange 'vx.builds'
|
12
|
+
queue 'vx.worker.builds'
|
13
|
+
ack true
|
14
|
+
|
15
|
+
model Message::PerformBuild
|
16
|
+
|
17
|
+
def perform(message)
|
18
|
+
logger.tagged self.class.consumer_id do
|
19
|
+
build = Build.new message
|
20
|
+
Router.new(build).perform
|
21
|
+
end
|
22
|
+
ack!
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'vx/common'
|
3
|
+
|
4
|
+
module Vx
|
5
|
+
class Router
|
6
|
+
class ScriptBuilder
|
7
|
+
|
8
|
+
autoload :Env, File.expand_path("../script_builder/env", __FILE__)
|
9
|
+
autoload :Ruby, File.expand_path("../script_builder/ruby", __FILE__)
|
10
|
+
autoload :Script, File.expand_path("../script_builder/script", __FILE__)
|
11
|
+
autoload :Prepare, File.expand_path("../script_builder/prepare", __FILE__)
|
12
|
+
autoload :Databases, File.expand_path("../script_builder/databases", __FILE__)
|
13
|
+
autoload :WebdavCache, File.expand_path("../script_builder/webdav_cache", __FILE__)
|
14
|
+
|
15
|
+
include Common::Helper::Middlewares
|
16
|
+
|
17
|
+
middlewares do
|
18
|
+
use ScriptBuilder::WebdavCache
|
19
|
+
use ScriptBuilder::Env
|
20
|
+
use ScriptBuilder::Prepare
|
21
|
+
use ScriptBuilder::Databases
|
22
|
+
use ScriptBuilder::Ruby
|
23
|
+
use ScriptBuilder::Script
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :configuration, :build
|
27
|
+
|
28
|
+
def initialize(build, configuration)
|
29
|
+
@configuration = configuration
|
30
|
+
@build = build
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_before_script
|
34
|
+
a = []
|
35
|
+
a << "\n# init"
|
36
|
+
a += env.init
|
37
|
+
|
38
|
+
a << "\n# before install"
|
39
|
+
a += env.before_install
|
40
|
+
|
41
|
+
a << "\n# announce"
|
42
|
+
a += env.announce
|
43
|
+
|
44
|
+
a << "\n# install"
|
45
|
+
a += env.install
|
46
|
+
|
47
|
+
a << "\n# before script"
|
48
|
+
a += env.before_script
|
49
|
+
a.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_after_script
|
53
|
+
a = []
|
54
|
+
a << "\n# after script"
|
55
|
+
a += env.after_script
|
56
|
+
a.join("\n")
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_script
|
60
|
+
a = []
|
61
|
+
a << "\n# script"
|
62
|
+
a += env.script
|
63
|
+
a.join("\n")
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def env
|
69
|
+
@env ||= run_middlewares(default_env) {|_| _ }
|
70
|
+
end
|
71
|
+
|
72
|
+
def default_env
|
73
|
+
OpenStruct.new(
|
74
|
+
# initialization, repo does not exists
|
75
|
+
init: [],
|
76
|
+
|
77
|
+
# before instalation, using for system setup
|
78
|
+
before_install: [],
|
79
|
+
|
80
|
+
# instalation, using for application setup
|
81
|
+
install: [],
|
82
|
+
|
83
|
+
# announce software and services version
|
84
|
+
announce: [],
|
85
|
+
|
86
|
+
before_script: [],
|
87
|
+
script: [],
|
88
|
+
after_script: [],
|
89
|
+
|
90
|
+
configuration: configuration,
|
91
|
+
build: build,
|
92
|
+
cache_key: []
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Vx
|
2
|
+
class Router
|
3
|
+
class ScriptBuilder
|
4
|
+
|
5
|
+
Databases = Struct.new(:app) do
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
psql = []
|
9
|
+
psql << %{sudo -u postgres psql -q -h localhost -c "create role ci with login superuser password 'ci'" || true}
|
10
|
+
psql << %{sudo -u postgres psql -q -h localhost -c "create database ci" || true}
|
11
|
+
|
12
|
+
mysql = []
|
13
|
+
|
14
|
+
mysql << %{echo "CREATE USER 'ci'@'localhost';" | mysql -u root }
|
15
|
+
mysql << %{echo "GRANT ALL PRIVILEGES ON *.* TO 'ci'@'localhost';" | mysql -u root }
|
16
|
+
|
17
|
+
env.init.tap do |i|
|
18
|
+
psql.each {|c| i << c }
|
19
|
+
mysql.each {|c| i << c }
|
20
|
+
end
|
21
|
+
|
22
|
+
app.call(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Vx
|
2
|
+
class Router
|
3
|
+
class ScriptBuilder
|
4
|
+
|
5
|
+
Env = Struct.new(:app) do
|
6
|
+
|
7
|
+
include Helper::TraceShCommand
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env.init << 'export LC_ALL=en_US.UTF8'
|
11
|
+
env.configuration.global_env.each do |e|
|
12
|
+
env.init << trace_sh_command("export #{e}")
|
13
|
+
end
|
14
|
+
env.announce << trace_sh_command("env")
|
15
|
+
app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|