konstant 0.0.8
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 +17 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +125 -0
- data/Rakefile +7 -0
- data/bin/konstant +87 -0
- data/data/templates/data_dir/konstant.js +16 -0
- data/data/templates/data_dir/projects/.gitkeep +0 -0
- data/data/templates/project/build +8 -0
- data/data/templates/project/cleanup +5 -0
- data/data/templates/project/deploy +4 -0
- data/data/templates/project/run.txt +0 -0
- data/konstant.gemspec +29 -0
- data/lib/konstant/build.rb +86 -0
- data/lib/konstant/builder.rb +108 -0
- data/lib/konstant/cli.rb +37 -0
- data/lib/konstant/project.rb +75 -0
- data/lib/konstant/runner.rb +50 -0
- data/lib/konstant/scheduler.rb +50 -0
- data/lib/konstant/version.rb +3 -0
- data/lib/konstant/web.rb +39 -0
- data/lib/konstant.rb +81 -0
- data/public/assets/angular.min.js +216 -0
- data/public/assets/app.js +60 -0
- data/public/assets/bootstrap-theme.min.css +5 -0
- data/public/assets/bootstrap.min.css +5 -0
- data/public/assets/bootstrap.min.js +6 -0
- data/public/assets/glyphicons-halflings-regular.eot +0 -0
- data/public/assets/glyphicons-halflings-regular.svg +229 -0
- data/public/assets/glyphicons-halflings-regular.ttf +0 -0
- data/public/assets/glyphicons-halflings-regular.woff +0 -0
- data/public/assets/jquery-2.1.1.min.js +4 -0
- data/public/assets/style.css +3 -0
- data/public/index.html +175 -0
- data/spec/file_spec.rb +28 -0
- data/spec/fixtures/projects/test_project_01/build +6 -0
- data/spec/fixtures/projects/test_project_02/build +3 -0
- data/spec/konstant/builder_spec.rb +21 -0
- data/spec/konstant/runner_spec.rb +14 -0
- data/spec/konstant_spec.rb +23 -0
- data/spec/spec_helper.rb +27 -0
- metadata +208 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Konstant::Runner
|
|
2
|
+
|
|
3
|
+
def initialize(build, task)
|
|
4
|
+
@build = build
|
|
5
|
+
@task = task
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_reader :build, :task
|
|
9
|
+
|
|
10
|
+
def run
|
|
11
|
+
if task == "build" || File.exists?("#{build.project.path}/#{task}")
|
|
12
|
+
duration = Konstant.measure do
|
|
13
|
+
build.create
|
|
14
|
+
File.open status_file, "w" do |f|
|
|
15
|
+
Bundler.with_clean_env do
|
|
16
|
+
system environment, "#{build.project.path}/#{task} > #{stdout_file} 2> #{stderr_file}"
|
|
17
|
+
f.puts $?.exitstatus
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
File.open "#{build.path}/#{task}.duration", "w" do |f|
|
|
22
|
+
f.puts duration
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
build.status(task) == 0
|
|
26
|
+
else
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def environment
|
|
32
|
+
return {
|
|
33
|
+
"KONSTANT_PROJECT_ROOT" => File.expand_path(build.project.path),
|
|
34
|
+
"KONSTANT_TIMESTAMP" => build.timestamp
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def stdout_file
|
|
39
|
+
"#{build.path}/#{task}.stdout"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def stderr_file
|
|
43
|
+
"#{build.path}/#{task}.stderr"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def status_file
|
|
47
|
+
"#{build.path}/#{task}.status"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Konstant::Scheduler
|
|
2
|
+
|
|
3
|
+
def run
|
|
4
|
+
@threads = {}
|
|
5
|
+
|
|
6
|
+
until Konstant.shutdown? do
|
|
7
|
+
project_paths = Dir["#{Konstant.config['data_dir']}/projects/*"]
|
|
8
|
+
project_ids = project_paths.map{|path| path.split('/').last}
|
|
9
|
+
|
|
10
|
+
(project_ids - @threads.keys).each do |project_id|
|
|
11
|
+
@threads[project_id] = project_worker(project_id)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
(@threads.keys - project_ids).each do |project_id|
|
|
15
|
+
thread = @thread.delete project_id
|
|
16
|
+
thread.kill
|
|
17
|
+
Konstant.logger.info "stopped worker for project '#{project_id}'"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
sleep Konstant.config['new_projects_interval']
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def project_worker(project_id)
|
|
25
|
+
Thread.new do
|
|
26
|
+
project = Konstant::Project.new(project_id)
|
|
27
|
+
Konstant.logger.info "started worker for project '#{project.id}'"
|
|
28
|
+
|
|
29
|
+
until Konstant.shutdown? do
|
|
30
|
+
Konstant.logger.debug "polling project '#{project.id}'"
|
|
31
|
+
if File.exists?("#{project.path}/run.txt")
|
|
32
|
+
system "rm #{project.path}/run.txt"
|
|
33
|
+
|
|
34
|
+
begin
|
|
35
|
+
system "touch #{project.path}/running.txt"
|
|
36
|
+
Konstant::Builder.new(project).run
|
|
37
|
+
rescue => e
|
|
38
|
+
puts e.message
|
|
39
|
+
puts e.backtrace
|
|
40
|
+
ensure
|
|
41
|
+
system "rm #{project.path}/running.txt"
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
sleep Konstant.config["build_check_interval"]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
data/lib/konstant/web.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "rack"
|
|
2
|
+
|
|
3
|
+
class Konstant::Web
|
|
4
|
+
|
|
5
|
+
def self.call(env)
|
|
6
|
+
new(env).route
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(env)
|
|
10
|
+
@env = env
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def request
|
|
14
|
+
@request ||= Rack::Request.new(@env)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def route
|
|
18
|
+
if request.path.match(/^\/projects$/)
|
|
19
|
+
[200, {"Content-type" => "application/json"}, [Konstant::Project.all.to_json]]
|
|
20
|
+
elsif m = request.path.match(/^\/projects\/([^\/]+)\/builds\/(\d+)$/)
|
|
21
|
+
project = Konstant::Project.new m[1]
|
|
22
|
+
build = Konstant::Build.new project, m[2]
|
|
23
|
+
[200, {"Content-type" => "application/json"}, [build.to_json]]
|
|
24
|
+
elsif request.path.match(/^\/config$/)
|
|
25
|
+
[200, {"Content-type" => "application/json"}, [Konstant.config.to_json]]
|
|
26
|
+
elsif m = request.path.match(/^\/projects\/([^\/]+)\/builds$/)
|
|
27
|
+
project = Konstant::Project.new m[1]
|
|
28
|
+
[200, {"Content-type" => "application/json"}, [project.builds.to_json]]
|
|
29
|
+
elsif m = request.path.match(/^\/projects\/([^\/]+)\/build$/)
|
|
30
|
+
project = Konstant::Project.new m[1]
|
|
31
|
+
project.build!
|
|
32
|
+
message = {"message" => "ok"}
|
|
33
|
+
[200, {"Content-type" => "application/json"}, [message.to_json]]
|
|
34
|
+
else
|
|
35
|
+
[404, {"Content-type" => "text/plain"}, ["not found"]]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
data/lib/konstant.rb
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require "konstant/version"
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
require "json"
|
|
5
|
+
require "mail"
|
|
6
|
+
|
|
7
|
+
module Konstant
|
|
8
|
+
|
|
9
|
+
autoload :Build, "konstant/build"
|
|
10
|
+
autoload :Builder, "konstant/builder"
|
|
11
|
+
autoload :Cli, "konstant/cli"
|
|
12
|
+
autoload :Project, "konstant/project"
|
|
13
|
+
autoload :Scheduler, "konstant/scheduler"
|
|
14
|
+
autoload :Runner, "konstant/runner"
|
|
15
|
+
autoload :Web, "konstant/web"
|
|
16
|
+
|
|
17
|
+
def self.config
|
|
18
|
+
@config ||= {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.configure(new_config)
|
|
22
|
+
case new_config
|
|
23
|
+
when Hash then config.merge! new_config
|
|
24
|
+
when String then config.merge! JSON.parse(File.read new_config)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.reset_config
|
|
29
|
+
@config = nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.reset_data_dir
|
|
33
|
+
system "rm -rf #{config['data_dir']}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.copy_fixture_projects
|
|
37
|
+
system "cp -a #{root}/data/templates/data_dir #{config['data_dir']}/"
|
|
38
|
+
system "cp -a #{root}/spec/fixtures/projects/* #{config['data_dir']}/projects/"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.env
|
|
42
|
+
ENV["RUBY_ENV"] || "development"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.root
|
|
46
|
+
File.expand_path(File.dirname(__FILE__) + "/..")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.shutdown!
|
|
50
|
+
@shutdown = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.shutdown?
|
|
54
|
+
@shutdown
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.shutdown_handlers
|
|
58
|
+
@shutdown_handlers ||= [
|
|
59
|
+
Proc.new { Konstant.shutdown! }
|
|
60
|
+
]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.logger
|
|
64
|
+
@logger ||= begin
|
|
65
|
+
result = Logger.new(STDOUT)
|
|
66
|
+
result.level = Logger::INFO
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.logger=(value)
|
|
72
|
+
@logger = value
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.measure
|
|
76
|
+
started_at = Time.now
|
|
77
|
+
yield
|
|
78
|
+
Time.now - started_at
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|