altria 0.2.0
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/Gemfile +41 -0
- data/LICENSE.txt +22 -0
- data/Procfile +4 -0
- data/README.md +40 -0
- data/Rakefile +6 -0
- data/altria.gemspec +50 -0
- data/app/assets/images/rails.png +0 -0
- data/app/assets/javascripts/altria.js.coffee +1 -0
- data/app/assets/javascripts/altria/build_view.js.coffee +13 -0
- data/app/assets/javascripts/altria/job_view.js.coffee +10 -0
- data/app/assets/javascripts/altria/server_event.js.coffee +8 -0
- data/app/assets/javascripts/application.js +20 -0
- data/app/assets/javascripts/events.js.coffee +13 -0
- data/app/assets/stylesheets/application.css +14 -0
- data/app/assets/stylesheets/builds.scss +35 -0
- data/app/assets/stylesheets/common.scss +69 -0
- data/app/assets/stylesheets/jobs.scss +129 -0
- data/app/assets/stylesheets/layout.scss +19 -0
- data/app/assets/stylesheets/mixin.scss +26 -0
- data/app/controllers/application_controller.rb +24 -0
- data/app/controllers/builds_controller.rb +48 -0
- data/app/controllers/events_controller.rb +27 -0
- data/app/controllers/jobs_controller.rb +50 -0
- data/app/helpers/application_helper.rb +5 -0
- data/app/models/build.rb +72 -0
- data/app/models/job.rb +141 -0
- data/app/views/builds/show.html.slim +36 -0
- data/app/views/jobs/_form.html.slim +22 -0
- data/app/views/jobs/edit.html.slim +9 -0
- data/app/views/jobs/index.html.slim +19 -0
- data/app/views/jobs/new.html.slim +7 -0
- data/app/views/jobs/show.html.slim +28 -0
- data/app/views/layouts/application.html.slim +11 -0
- data/app/workers/build_worker.rb +13 -0
- data/app/workers/job_enqueue_worker.rb +13 -0
- data/bin/altria +6 -0
- data/config.ru +4 -0
- data/config/application.rb +52 -0
- data/config/boot.rb +6 -0
- data/config/database.yml +29 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +23 -0
- data/config/environments/production.rb +71 -0
- data/config/environments/test.rb +33 -0
- data/config/initializers/backtrace_silencers.rb +7 -0
- data/config/initializers/inflections.rb +15 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/redis.rb +1 -0
- data/config/initializers/secret_token.rb +8 -0
- data/config/initializers/session_store.rb +8 -0
- data/config/initializers/wrap_parameters.rb +14 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20130531143239_create_jobs.rb +10 -0
- data/db/migrate/20130531155155_create_builds.rb +14 -0
- data/db/migrate/20130608153135_change_job_column_name_from_config_to_properties.rb +9 -0
- data/db/migrate/20130608153655_add_column_properties_to_builds.rb +5 -0
- data/db/schema.rb +36 -0
- data/db/seeds.rb +7 -0
- data/lib/altria.rb +13 -0
- data/lib/altria/command.rb +61 -0
- data/lib/altria/configuration.rb +9 -0
- data/lib/altria/executer.rb +37 -0
- data/lib/altria/proprietary.rb +56 -0
- data/lib/altria/responder.rb +12 -0
- data/lib/altria/scheduler.rb +55 -0
- data/lib/altria/version.rb +3 -0
- data/lib/altria/workspace.rb +26 -0
- data/lib/tasks/resque.rake +3 -0
- data/public/404.html +26 -0
- data/public/422.html +26 -0
- data/public/500.html +25 -0
- data/public/favicon.ico +0 -0
- data/public/robots.txt +5 -0
- data/script/clock.rb +5 -0
- data/script/rails +6 -0
- data/spec/altria/command_spec.rb +53 -0
- data/spec/factories/build.rb +7 -0
- data/spec/factories/job.rb +7 -0
- data/spec/models/build_spec.rb +35 -0
- data/spec/models/job_spec.rb +101 -0
- data/spec/requests/builds_spec.rb +81 -0
- data/spec/requests/jobs_spec.rb +88 -0
- data/spec/spec_helper.rb +48 -0
- metadata +417 -0
data/public/500.html
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/500.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>We're sorry, but something went wrong.</h1>
|
23
|
+
</div>
|
24
|
+
</body>
|
25
|
+
</html>
|
data/public/favicon.ico
ADDED
File without changes
|
data/public/robots.txt
ADDED
data/script/clock.rb
ADDED
data/script/rails
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Altria::Command do
|
4
|
+
let(:command) do
|
5
|
+
described_class.new(arguments)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".call" do
|
9
|
+
it "delegates to #call" do
|
10
|
+
described_class.any_instance.should_receive(:call)
|
11
|
+
described_class.call(["setup"])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#call" do
|
16
|
+
let(:env) do
|
17
|
+
{ "WORKSPACE_PATH" => Dir.pwd }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with `setup`" do
|
21
|
+
let(:arguments) do
|
22
|
+
["setup"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "executes setup script" do
|
26
|
+
command.should_receive(:system).with(env, "cd #{Dir.pwd} && bundle install && bundle exec rake db:create db:migrate")
|
27
|
+
command.call
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with `start`" do
|
32
|
+
let(:arguments) do
|
33
|
+
["start"]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "executes start script" do
|
37
|
+
command.should_receive(:system).with(env, "cd #{Dir.pwd} && bundle exec foreman start")
|
38
|
+
command.call
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with unknown arguments" do
|
43
|
+
let(:arguments) do
|
44
|
+
[]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "shows usage" do
|
48
|
+
command.should_receive(:puts).with("Usage: altria {setup|start}")
|
49
|
+
command.call
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Build do
|
4
|
+
let(:build) do
|
5
|
+
FactoryGirl.create(:build, job: job)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:job) do
|
9
|
+
FactoryGirl.create(:job, properties: { "script" => "true" })
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#run" do
|
13
|
+
context "with success" do
|
14
|
+
it "runs its job and sets status with true" do
|
15
|
+
build.run
|
16
|
+
build.started_at.should be_present
|
17
|
+
build.finished_at.should be_present
|
18
|
+
build.status.should == true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with failure" do
|
23
|
+
before do
|
24
|
+
build.job.script = "false"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "runs its job and sets status with false" do
|
28
|
+
build.run
|
29
|
+
build.started_at.should be_present
|
30
|
+
build.finished_at.should be_present
|
31
|
+
build.status.should == false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Job do
|
4
|
+
let(:job) do
|
5
|
+
FactoryGirl.create(:job, properties: { "script" => "true" })
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#run" do
|
9
|
+
context "without script" do
|
10
|
+
before do
|
11
|
+
job.script = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises Job::ScriptNotFound" do
|
15
|
+
expect { job.run }.to raise_error(Job::ScriptNotFound)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with script" do
|
20
|
+
before do
|
21
|
+
job.script = "true"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "runs its job" do
|
25
|
+
Altria::Executer.should_receive(:execute).with("true")
|
26
|
+
job.run
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#scheduled?" do
|
32
|
+
context "without schedule" do
|
33
|
+
it "returns false" do
|
34
|
+
job.should_not be_scheduled
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with empty schedule" do
|
39
|
+
before do
|
40
|
+
job.schedule = ""
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns false" do
|
44
|
+
job.should_not be_scheduled
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with matched schedule" do
|
49
|
+
before do
|
50
|
+
job.schedule = "* * * * *"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns true" do
|
54
|
+
job.should be_scheduled
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "without matched schedule" do
|
59
|
+
before do
|
60
|
+
job.schedule = "0 0 0 0 0"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns false" do
|
64
|
+
job.should_not be_scheduled
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#enqueue_with_before_enqueues" do
|
70
|
+
before do
|
71
|
+
Job.before_enqueues.clear
|
72
|
+
end
|
73
|
+
|
74
|
+
after do
|
75
|
+
Job.before_enqueues.clear
|
76
|
+
end
|
77
|
+
|
78
|
+
context "with successful hooks" do
|
79
|
+
before do
|
80
|
+
Job.before_enqueue { Job.hook_is_executed }
|
81
|
+
end
|
82
|
+
|
83
|
+
it "enqueues a new build" do
|
84
|
+
Job.should_receive(:hook_is_executed)
|
85
|
+
job.enqueue_with_before_enqueues
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with failed hooks" do
|
90
|
+
before do
|
91
|
+
Job.before_enqueue { false }
|
92
|
+
Job.before_enqueue { Job.hook_is_executed }
|
93
|
+
end
|
94
|
+
|
95
|
+
it "stops at failed hook" do
|
96
|
+
Job.should_not_receive(:hook_is_executed)
|
97
|
+
job.enqueue_with_before_enqueues
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Builds" do
|
4
|
+
let(:params) do
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:env) do
|
9
|
+
{ "HTTP_ACCEPT" => "application/json" }
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:job) do
|
13
|
+
FactoryGirl.create(:job, properties: { "script" => "true" })
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:build) do
|
17
|
+
job.builds.create(id: 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "GET /jobs/:job_id/builds" do
|
21
|
+
before do
|
22
|
+
build
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns builds of the job", :autodoc do
|
26
|
+
get "/jobs/#{job.id}/builds", params, env
|
27
|
+
response.status.should == 200
|
28
|
+
response.body.should be_json([Hash])
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with page" do
|
32
|
+
before do
|
33
|
+
params[:page] = 2
|
34
|
+
10.times { job.builds.create }
|
35
|
+
end
|
36
|
+
|
37
|
+
it "paginates builds" do
|
38
|
+
get "/jobs/#{job.id}/builds", params, env
|
39
|
+
response.status.should == 200
|
40
|
+
response.body.should be_json([Hash])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "GET /jobs/:job_id/builds/:id" do
|
46
|
+
it "returns the build", :autodoc do
|
47
|
+
get "/jobs/#{job.id}/builds/#{build.id}", params, env
|
48
|
+
response.status.should == 200
|
49
|
+
response.body.should be_json(Hash)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "POST /jobs/:job_id/builds" do
|
54
|
+
it "creates a new build and queue it", :autodoc do
|
55
|
+
post "/jobs/#{job.id}/builds", params, env
|
56
|
+
response.status.should == 201
|
57
|
+
response.body.should be_json(Hash)
|
58
|
+
job.builds.should have(1).builds
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "PUT /jobs/:job_id/builds/:id" do
|
63
|
+
before do
|
64
|
+
params[:status] = 1
|
65
|
+
end
|
66
|
+
|
67
|
+
it "updates the build", :autodoc do
|
68
|
+
put "/jobs/#{job.id}/builds/#{build.id}", params, env
|
69
|
+
response.status.should == 204
|
70
|
+
build.reload.status.should == true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "DELETE /jobs/:job_id/builds/:id" do
|
75
|
+
it "deletes the build", :autodoc do
|
76
|
+
delete "/jobs/#{job.id}/builds/#{build.id}", params, env
|
77
|
+
response.status.should == 204
|
78
|
+
Build.should have(0).build
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Jobs" do
|
4
|
+
let(:params) do
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:env) do
|
9
|
+
{ "HTTP_ACCEPT" => "application/json" }
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:job) do
|
13
|
+
FactoryGirl.create(:job)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "GET /jobs" do
|
17
|
+
before do
|
18
|
+
job
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns jobs", :autodoc do
|
22
|
+
get "/jobs", params, env
|
23
|
+
response.status.should == 200
|
24
|
+
response.body.should be_json([Hash])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "GET /jobs/:id" do
|
29
|
+
it "returns the job", :autodoc do
|
30
|
+
get "/jobs/#{job.id}", params, env
|
31
|
+
response.status.should == 200
|
32
|
+
response.body.should be_json(Hash)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "POST /jobs" do
|
37
|
+
before do
|
38
|
+
params[:name] = "name"
|
39
|
+
params[:description] = "description"
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with invalid params" do
|
43
|
+
before do
|
44
|
+
params.delete(:name)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns 400" do
|
48
|
+
post "/jobs", params, env
|
49
|
+
response.status.should == 400
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with valid condition" do
|
54
|
+
it "creates a new job", :autodoc do
|
55
|
+
post "/jobs", params, env
|
56
|
+
response.status.should == 201
|
57
|
+
job = Job.first
|
58
|
+
job.name.should == "name"
|
59
|
+
job.description.should == "description"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "PUT /jobs/:id" do
|
65
|
+
before do
|
66
|
+
params[:name] = "name"
|
67
|
+
params[:description] = "description"
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with valid condition" do
|
71
|
+
it "updates the job", :autodoc do
|
72
|
+
put "/jobs/#{job.id}", params, env
|
73
|
+
response.status.should == 204
|
74
|
+
job.reload
|
75
|
+
job.name.should == "name"
|
76
|
+
job.description.should == "description"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "DELETE /jobs/:id" do
|
82
|
+
it "deletes the job" do
|
83
|
+
delete "/jobs/#{job.id}", params, env
|
84
|
+
response.status.should == 204
|
85
|
+
Job.should_not be_exist(job.id)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
require "coveralls"
|
3
|
+
Coveralls.wear!
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
Coveralls::SimpleCov::Formatter,
|
7
|
+
]
|
8
|
+
SimpleCov.start
|
9
|
+
|
10
|
+
ENV["RAILS_ENV"] ||= "test"
|
11
|
+
require File.expand_path("../../config/environment", __FILE__)
|
12
|
+
require "rspec/rails"
|
13
|
+
require "rspec/autorun"
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
# If you"re not using ActiveRecord, or you"d prefer not to run each of your
|
17
|
+
# examples within a transaction, remove the following line or assign false
|
18
|
+
# instead of true.
|
19
|
+
config.use_transactional_fixtures = true
|
20
|
+
|
21
|
+
# If true, the base class of anonymous controllers will be inferred
|
22
|
+
# automatically. This will be the default behavior in future versions of
|
23
|
+
# rspec-rails.
|
24
|
+
config.infer_base_class_for_anonymous_controllers = false
|
25
|
+
|
26
|
+
# Enables :focus metadata filter.
|
27
|
+
config.filter_run :focus
|
28
|
+
config.run_all_when_everything_filtered = true
|
29
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
30
|
+
|
31
|
+
config.include RSpec::JsonMatcher, type: :request
|
32
|
+
config.include ResponseCodeMatchers, type: :request
|
33
|
+
|
34
|
+
config.before(:suite) do
|
35
|
+
Altria.configuration.workspace_path = Rails.root.join("tmp/workspace")
|
36
|
+
end
|
37
|
+
|
38
|
+
config.after(:suite) do
|
39
|
+
workspace = Rails.root.join("tmp/workspace")
|
40
|
+
workspace.rmtree if workspace.exist?
|
41
|
+
end
|
42
|
+
|
43
|
+
config.before do
|
44
|
+
$redis.stub(:publish)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Resque.inline = true
|