altria 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/config/routes.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateBuilds < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :builds do |t|
|
4
|
+
t.boolean :status
|
5
|
+
t.datetime :started_at
|
6
|
+
t.datetime :finished_at
|
7
|
+
t.references :job
|
8
|
+
t.text :output
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
add_index :builds, :job_id
|
13
|
+
end
|
14
|
+
end
|
data/db/schema.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20130608153655) do
|
15
|
+
|
16
|
+
create_table "builds", force: true do |t|
|
17
|
+
t.boolean "status"
|
18
|
+
t.datetime "started_at"
|
19
|
+
t.datetime "finished_at"
|
20
|
+
t.integer "job_id"
|
21
|
+
t.text "output"
|
22
|
+
t.datetime "created_at"
|
23
|
+
t.datetime "updated_at"
|
24
|
+
t.text "properties"
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index "builds", ["job_id"], name: "index_builds_on_job_id", using: :btree
|
28
|
+
|
29
|
+
create_table "jobs", force: true do |t|
|
30
|
+
t.string "name"
|
31
|
+
t.text "properties"
|
32
|
+
t.datetime "created_at"
|
33
|
+
t.datetime "updated_at"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# This file should contain all the record creation needed to seed the database with its default values.
|
2
|
+
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
3
|
+
#
|
4
|
+
# Examples:
|
5
|
+
#
|
6
|
+
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
7
|
+
# Mayor.create(name: 'Emanuel', city: cities.first)
|
data/lib/altria.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "altria/command"
|
2
|
+
require "altria/configuration"
|
3
|
+
require "altria/responder"
|
4
|
+
require "altria/version"
|
5
|
+
require "altria/workspace"
|
6
|
+
|
7
|
+
module Altria
|
8
|
+
class << self
|
9
|
+
def configuration
|
10
|
+
@configuration ||= Altria::Configuration.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Provides command line interface for Altria.
|
2
|
+
#
|
3
|
+
# Examples
|
4
|
+
#
|
5
|
+
# # Takes ARGV and invokes a job.
|
6
|
+
# Altria::Command.call(ARGV)
|
7
|
+
#
|
8
|
+
# # Invokes "setup" command to set up your database.
|
9
|
+
# Altria::Command.call(["setup"])
|
10
|
+
#
|
11
|
+
# # Invokes "start" command to start the processes.
|
12
|
+
# Altria::Command.call(["start"])
|
13
|
+
#
|
14
|
+
module Altria
|
15
|
+
class Command
|
16
|
+
def self.call(*args)
|
17
|
+
new(*args).call
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(argv)
|
21
|
+
@argv = argv
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
case name
|
26
|
+
when "setup"
|
27
|
+
setup
|
28
|
+
when "start"
|
29
|
+
start
|
30
|
+
else
|
31
|
+
puts "Usage: altria {setup|start}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def name
|
38
|
+
@argv[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
system(env, "cd #{root_path} && bundle install && bundle exec rake db:create db:migrate")
|
43
|
+
end
|
44
|
+
|
45
|
+
def start
|
46
|
+
system(env, "cd #{root_path} && bundle exec foreman start")
|
47
|
+
end
|
48
|
+
|
49
|
+
def root_path
|
50
|
+
File.expand_path("../../..", __FILE__)
|
51
|
+
end
|
52
|
+
|
53
|
+
def workspace_path
|
54
|
+
Dir.pwd
|
55
|
+
end
|
56
|
+
|
57
|
+
def env
|
58
|
+
{ "WORKSPACE_PATH" => workspace_path }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "open3"
|
2
|
+
|
3
|
+
module Altria
|
4
|
+
class Executer
|
5
|
+
def self.execute(*args)
|
6
|
+
new(*args).execute
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :script
|
10
|
+
|
11
|
+
def initialize(script)
|
12
|
+
@script = script
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
{ output: output, status: status.success? }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def output
|
22
|
+
result[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def status
|
26
|
+
result[1]
|
27
|
+
end
|
28
|
+
|
29
|
+
def result
|
30
|
+
@result ||= Open3.capture2e(lines)
|
31
|
+
end
|
32
|
+
|
33
|
+
def lines
|
34
|
+
script.gsub("\n", ";")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Altria
|
2
|
+
module Proprietary
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def update_properties(properties)
|
6
|
+
properties.each do |key, value|
|
7
|
+
send("#{key}=", value)
|
8
|
+
end
|
9
|
+
save
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def property(name, options = {})
|
14
|
+
property = Property.new(name, options)
|
15
|
+
properties << property
|
16
|
+
|
17
|
+
define_method(name) do
|
18
|
+
properties[name.to_s]
|
19
|
+
end
|
20
|
+
|
21
|
+
define_method("#{name}=") do |value|
|
22
|
+
properties[name.to_s] = begin
|
23
|
+
case
|
24
|
+
when property.type != :boolean
|
25
|
+
value
|
26
|
+
when value.to_s == "false"
|
27
|
+
false
|
28
|
+
else
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def properties
|
36
|
+
@properties ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
def property_names
|
40
|
+
properties.map(&:name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Property
|
45
|
+
attr_reader :name, :options
|
46
|
+
|
47
|
+
def initialize(name, options = {})
|
48
|
+
@name, @options = name, options
|
49
|
+
end
|
50
|
+
|
51
|
+
def type
|
52
|
+
options[:type] || :string
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "action_controller"
|
2
|
+
|
3
|
+
module Altria
|
4
|
+
class Responder < ActionController::Responder
|
5
|
+
def initialize(controller, resources, *args)
|
6
|
+
if resources[0].respond_to?(:page)
|
7
|
+
resources[0] = resources[0].page(controller.params[:page])
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Altria
|
2
|
+
class Scheduler
|
3
|
+
CRON_REGEXP = /\A(\d+|\*) (\d+|\*) (\d+|\*) (\d+|\*) (\d+|\*)\s*\z/
|
4
|
+
|
5
|
+
# Takes a schedule as a String.
|
6
|
+
def initialize(schedule)
|
7
|
+
@result, @min, @hour, @day, @month, @wday = *schedule.match(CRON_REGEXP)
|
8
|
+
validate
|
9
|
+
end
|
10
|
+
|
11
|
+
def scheduled?
|
12
|
+
[:min, :hour, :day, :month, :wday].all? do |key|
|
13
|
+
send(key).nil? || send(key) == now.send(key)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def min
|
20
|
+
@min.to_i if @min != "*"
|
21
|
+
end
|
22
|
+
|
23
|
+
def hour
|
24
|
+
@hour.to_i if @hour != "*"
|
25
|
+
end
|
26
|
+
|
27
|
+
def day
|
28
|
+
@day.to_i if @day != "*"
|
29
|
+
end
|
30
|
+
|
31
|
+
def month
|
32
|
+
@month.to_i if @month != "*"
|
33
|
+
end
|
34
|
+
|
35
|
+
def wday
|
36
|
+
@wday.to_i if @wday != "*"
|
37
|
+
end
|
38
|
+
|
39
|
+
def now
|
40
|
+
@now ||= Time.now
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate
|
44
|
+
raise_argument_error unless valid?
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid?
|
48
|
+
!!@result
|
49
|
+
end
|
50
|
+
|
51
|
+
def raise_argument_error
|
52
|
+
raise ArgumentError, "Input must match with #{CRON_REGEXP}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Altria
|
2
|
+
class Workspace
|
3
|
+
attr_reader :path
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
@path = Pathname.new(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def chdir
|
10
|
+
mkpath_unless_exist
|
11
|
+
Dir.chdir(path) { yield }
|
12
|
+
end
|
13
|
+
|
14
|
+
def mkpath_unless_exist
|
15
|
+
mkpath unless exist?
|
16
|
+
end
|
17
|
+
|
18
|
+
def mkpath
|
19
|
+
path.mkpath
|
20
|
+
end
|
21
|
+
|
22
|
+
def exist?
|
23
|
+
path.exist?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/public/404.html
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</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/404.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
23
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
data/public/422.html
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</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/422.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The change you wanted was rejected.</h1>
|
23
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|