altria 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +41 -0
  3. data/LICENSE.txt +22 -0
  4. data/Procfile +4 -0
  5. data/README.md +40 -0
  6. data/Rakefile +6 -0
  7. data/altria.gemspec +50 -0
  8. data/app/assets/images/rails.png +0 -0
  9. data/app/assets/javascripts/altria.js.coffee +1 -0
  10. data/app/assets/javascripts/altria/build_view.js.coffee +13 -0
  11. data/app/assets/javascripts/altria/job_view.js.coffee +10 -0
  12. data/app/assets/javascripts/altria/server_event.js.coffee +8 -0
  13. data/app/assets/javascripts/application.js +20 -0
  14. data/app/assets/javascripts/events.js.coffee +13 -0
  15. data/app/assets/stylesheets/application.css +14 -0
  16. data/app/assets/stylesheets/builds.scss +35 -0
  17. data/app/assets/stylesheets/common.scss +69 -0
  18. data/app/assets/stylesheets/jobs.scss +129 -0
  19. data/app/assets/stylesheets/layout.scss +19 -0
  20. data/app/assets/stylesheets/mixin.scss +26 -0
  21. data/app/controllers/application_controller.rb +24 -0
  22. data/app/controllers/builds_controller.rb +48 -0
  23. data/app/controllers/events_controller.rb +27 -0
  24. data/app/controllers/jobs_controller.rb +50 -0
  25. data/app/helpers/application_helper.rb +5 -0
  26. data/app/models/build.rb +72 -0
  27. data/app/models/job.rb +141 -0
  28. data/app/views/builds/show.html.slim +36 -0
  29. data/app/views/jobs/_form.html.slim +22 -0
  30. data/app/views/jobs/edit.html.slim +9 -0
  31. data/app/views/jobs/index.html.slim +19 -0
  32. data/app/views/jobs/new.html.slim +7 -0
  33. data/app/views/jobs/show.html.slim +28 -0
  34. data/app/views/layouts/application.html.slim +11 -0
  35. data/app/workers/build_worker.rb +13 -0
  36. data/app/workers/job_enqueue_worker.rb +13 -0
  37. data/bin/altria +6 -0
  38. data/config.ru +4 -0
  39. data/config/application.rb +52 -0
  40. data/config/boot.rb +6 -0
  41. data/config/database.yml +29 -0
  42. data/config/environment.rb +5 -0
  43. data/config/environments/development.rb +23 -0
  44. data/config/environments/production.rb +71 -0
  45. data/config/environments/test.rb +33 -0
  46. data/config/initializers/backtrace_silencers.rb +7 -0
  47. data/config/initializers/inflections.rb +15 -0
  48. data/config/initializers/mime_types.rb +5 -0
  49. data/config/initializers/redis.rb +1 -0
  50. data/config/initializers/secret_token.rb +8 -0
  51. data/config/initializers/session_store.rb +8 -0
  52. data/config/initializers/wrap_parameters.rb +14 -0
  53. data/config/locales/en.yml +5 -0
  54. data/config/routes.rb +9 -0
  55. data/db/migrate/20130531143239_create_jobs.rb +10 -0
  56. data/db/migrate/20130531155155_create_builds.rb +14 -0
  57. data/db/migrate/20130608153135_change_job_column_name_from_config_to_properties.rb +9 -0
  58. data/db/migrate/20130608153655_add_column_properties_to_builds.rb +5 -0
  59. data/db/schema.rb +36 -0
  60. data/db/seeds.rb +7 -0
  61. data/lib/altria.rb +13 -0
  62. data/lib/altria/command.rb +61 -0
  63. data/lib/altria/configuration.rb +9 -0
  64. data/lib/altria/executer.rb +37 -0
  65. data/lib/altria/proprietary.rb +56 -0
  66. data/lib/altria/responder.rb +12 -0
  67. data/lib/altria/scheduler.rb +55 -0
  68. data/lib/altria/version.rb +3 -0
  69. data/lib/altria/workspace.rb +26 -0
  70. data/lib/tasks/resque.rake +3 -0
  71. data/public/404.html +26 -0
  72. data/public/422.html +26 -0
  73. data/public/500.html +25 -0
  74. data/public/favicon.ico +0 -0
  75. data/public/robots.txt +5 -0
  76. data/script/clock.rb +5 -0
  77. data/script/rails +6 -0
  78. data/spec/altria/command_spec.rb +53 -0
  79. data/spec/factories/build.rb +7 -0
  80. data/spec/factories/job.rb +7 -0
  81. data/spec/models/build_spec.rb +35 -0
  82. data/spec/models/job_spec.rb +101 -0
  83. data/spec/requests/builds_spec.rb +81 -0
  84. data/spec/requests/jobs_spec.rb +88 -0
  85. data/spec/spec_helper.rb +48 -0
  86. metadata +417 -0
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: "Hello world"
data/config/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ Altria::Application.routes.draw do
2
+ root to: "jobs#index"
3
+
4
+ resources :jobs do
5
+ resources :builds, only: [:index, :show, :create, :update, :destroy]
6
+ end
7
+
8
+ resources :events, only: :index if Rails.configuration.cache_classes
9
+ end
@@ -0,0 +1,10 @@
1
+ class CreateJobs < ActiveRecord::Migration
2
+ def change
3
+ create_table :jobs do |t|
4
+ t.string :name
5
+ t.text :config
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ class ChangeJobColumnNameFromConfigToProperties < ActiveRecord::Migration
2
+ def up
3
+ rename_column :jobs, :config, :properties
4
+ end
5
+
6
+ def down
7
+ rename_column :jobs, :properties, :config
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AddColumnPropertiesToBuilds < ActiveRecord::Migration
2
+ def change
3
+ add_column :builds, :properties, :text
4
+ end
5
+ 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,9 @@
1
+ module Altria
2
+ class Configuration
3
+ attr_accessor :workspace_path
4
+
5
+ def initialize
6
+ @workspace_path = Pathname.new(ENV["WORKSPACE_PATH"] || ".")
7
+ end
8
+ end
9
+ 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,3 @@
1
+ module Altria
2
+ VERSION = "0.2.0"
3
+ 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
@@ -0,0 +1,3 @@
1
+ require "resque/tasks"
2
+
3
+ task "resque:setup" => :environment
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>