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.
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>