etsy-deployinator 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +368 -0
  5. data/Rakefile +16 -0
  6. data/bin/deployinator-tailer.rb +78 -0
  7. data/deployinator.gemspec +31 -0
  8. data/lib/deployinator.rb +114 -0
  9. data/lib/deployinator/app.rb +204 -0
  10. data/lib/deployinator/base.rb +58 -0
  11. data/lib/deployinator/config.rb +7 -0
  12. data/lib/deployinator/controller.rb +147 -0
  13. data/lib/deployinator/helpers.rb +610 -0
  14. data/lib/deployinator/helpers/deploy.rb +68 -0
  15. data/lib/deployinator/helpers/dsh.rb +42 -0
  16. data/lib/deployinator/helpers/git.rb +348 -0
  17. data/lib/deployinator/helpers/plugin.rb +50 -0
  18. data/lib/deployinator/helpers/stack-tail.rb +32 -0
  19. data/lib/deployinator/helpers/version.rb +62 -0
  20. data/lib/deployinator/helpers/view.rb +67 -0
  21. data/lib/deployinator/logging.rb +16 -0
  22. data/lib/deployinator/plugin.rb +7 -0
  23. data/lib/deployinator/stack-tail.rb +34 -0
  24. data/lib/deployinator/static/css/diff_style.css +283 -0
  25. data/lib/deployinator/static/css/highlight.css +235 -0
  26. data/lib/deployinator/static/css/style.css +1223 -0
  27. data/lib/deployinator/static/js/flot/jquery.flot.min.js +1 -0
  28. data/lib/deployinator/static/js/flot/jquery.flot.selection.js +299 -0
  29. data/lib/deployinator/static/js/jquery-1.8.3.min.js +2 -0
  30. data/lib/deployinator/static/js/jquery-ui-1.8.24.min.js +5 -0
  31. data/lib/deployinator/static/js/jquery.timed_bar.js +36 -0
  32. data/lib/deployinator/tasks/initialize.rake +84 -0
  33. data/lib/deployinator/tasks/tests.rake +22 -0
  34. data/lib/deployinator/templates/deploys_status.mustache +42 -0
  35. data/lib/deployinator/templates/generic_single_push.mustache +64 -0
  36. data/lib/deployinator/templates/index.mustache +12 -0
  37. data/lib/deployinator/templates/layout.mustache +604 -0
  38. data/lib/deployinator/templates/log.mustache +24 -0
  39. data/lib/deployinator/templates/log_table.mustache +90 -0
  40. data/lib/deployinator/templates/messageboxes.mustache +29 -0
  41. data/lib/deployinator/templates/run_logs.mustache +15 -0
  42. data/lib/deployinator/templates/scroll_control.mustache +8 -0
  43. data/lib/deployinator/templates/stream.mustache +13 -0
  44. data/lib/deployinator/version.rb +3 -0
  45. data/lib/deployinator/views/deploys_status.rb +22 -0
  46. data/lib/deployinator/views/index.rb +14 -0
  47. data/lib/deployinator/views/layout.rb +48 -0
  48. data/lib/deployinator/views/log.rb +12 -0
  49. data/lib/deployinator/views/log_table.rb +35 -0
  50. data/lib/deployinator/views/run_logs.rb +32 -0
  51. data/templates/app.rb.erb +7 -0
  52. data/templates/config.ru.erb +10 -0
  53. data/templates/helper.rb.erb +15 -0
  54. data/templates/stack.rb.erb +17 -0
  55. data/templates/template.mustache +1 -0
  56. data/templates/view.rb.erb +7 -0
  57. data/test/unit/helpers_dsh_test.rb +40 -0
  58. data/test/unit/helpers_test.rb +77 -0
  59. data/test/unit/version_test.rb +104 -0
  60. metadata +245 -0
@@ -0,0 +1,24 @@
1
+ <ol id="log">
2
+ {{# log_lines }}
3
+ <li class="{{env}} {{stack}} {{is_prod}}">
4
+ {{stack}} &ndash;
5
+ <span title="{{time}}" data-timestamp="{{time_secs}}" class="timestamp">{{timestamp}}</span> |
6
+ <span class="env">{{env}}</span> |
7
+ {{who}} |
8
+ {{{msg}}}
9
+ {{# run_log_url}}
10
+ <a href="/run_logs/view/{{run_log_url}}">run log</a>
11
+ {{/ run_log_url}}
12
+ {{# new}} |
13
+ {{# diff_url}}
14
+ <a href="/{{diff_method}}/{{stack}}/{{old}}/{{new}}?time={{time_secs}}" target="_blank">diff</a>
15
+ {{/ diff_url}}
16
+
17
+ {{# dashboards_host }}
18
+ <a href="http://{{ dashboards_host }}/deploy.php?m=1&time={{ from_timestamp }}&until={{ until_timestamp }}&error_log=_all" target="_blank">dashboard</a>
19
+ {{/ dashboards_host }}
20
+
21
+ {{/ new}}
22
+ </li>
23
+ {{/ log_lines }}
24
+ </ol>
@@ -0,0 +1,90 @@
1
+ <table id="log">
2
+ <thead>
3
+ <tr>
4
+ <th>
5
+ {{# prev_page }}
6
+ <a href="?page={{prev_page}}">prev</a>
7
+ {{/ prev_page }}
8
+ </th>
9
+ <th></th>
10
+ <th></th>
11
+ <th></th>
12
+ <th></th>
13
+ <th></th>
14
+ <th></th>
15
+ <th>
16
+ <a href="?page={{next_page}}">next</a>
17
+ </th>
18
+ </tr>
19
+ <tr>
20
+ <th>Stack</th>
21
+ <th>When (UTC)</th>
22
+ <th>Info</th>
23
+ <th>Who</th>
24
+ <th>Message</th>
25
+ <th>Run Log</th>
26
+ <th>Diff</th>
27
+ {{# dashboards? }}
28
+ <th>Dashboard</th>
29
+ {{/ dashboards? }}
30
+ {{# show_counts? }}
31
+ <th>+/-</th>
32
+ {{/ show_counts? }}
33
+ </tr>
34
+ </thead>
35
+ <tbody>
36
+ {{# log_lines }}
37
+ <tr class="{{env}} {{is_prod}}">
38
+ <td>{{stack}}</td>
39
+ <td><span title="{{timestamp}}" class="timestamp" data-timestamp="{{time_secs}}">{{time}}</span></td>
40
+ <td>{{env}}</td>
41
+ <td>{{who}}</td>
42
+ <td>{{{msg}}}</td>
43
+ <td>
44
+ {{# run_log_url }}
45
+ <a href="/run_logs/view/{{run_log_url}}">run log</a>
46
+ {{/ run_log_url }}
47
+ </td>
48
+ <td>
49
+ {{# new}}
50
+ <a href="/{{diff_method}}/{{stack}}/{{old}}/{{new}}" target="_blank">diff</a>
51
+ {{/ new}}
52
+ </td>
53
+ {{# dashboards? }}
54
+ <td>
55
+ <a href="http://{{ dashboards_host }}/deploy.php?m=1&time={{ from_timestamp }}&until={{ until_timestamp }}&error_log=_all" target="_blank">dashboard</a>
56
+ </td>
57
+ {{/ dashboards? }}
58
+ {{# show_counts? }}
59
+ <td>
60
+ {{counts}}
61
+ </td>
62
+ {{/ show_counts? }}
63
+ </tr>
64
+ {{/ log_lines }}
65
+
66
+ <tr>
67
+ <th>
68
+ {{# prev_page }}
69
+ <form action="/log">
70
+ <input type="hidden" name="page" value="{{prev_page}}" />
71
+ <button class="button small">Prev</button>
72
+ </form>
73
+ {{/ prev_page }}
74
+ </th>
75
+ <th></th>
76
+ <th></th>
77
+ <th></th>
78
+ <th></th>
79
+ <th></th>
80
+ <th>
81
+ <form action="/log">
82
+ <input type="hidden" name="page" value="{{next_page}}" />
83
+ <button class="button small">Next</button>
84
+ </form>
85
+
86
+ </th>
87
+ </tr>
88
+
89
+ </tbody>
90
+ </table>
@@ -0,0 +1,29 @@
1
+ <div id="error_report" class="display-panel">
2
+ <h1>Error Log</h1>
3
+ </div>
4
+ <div id="warning_report" class="display-panel">
5
+ <h1>Warnings</h1>
6
+ </div>
7
+ <div id="info_msg_report" class="display-panel">
8
+ <h1>Information Log</h1>
9
+ {{# disabled_override }}
10
+ <h3>You have chosen to override version checking. Hic sunt dracones.</h3>
11
+ <p> Stuff known not to work properly without a valid version rev:
12
+ <ul style="list-style-position: inside">
13
+ <li> Diff URLs </li>
14
+ <li> Jenkins build notifications </li>
15
+ </ul>
16
+ </p>
17
+ <script>$('#info_msg_report').show();</script>
18
+ {{/ disabled_override }}
19
+ {{^ allowed_to_push_to_prod?}}
20
+ <div id="not-allowed-to-prod">
21
+ Oops, looks like you can't push to prod yet. Just ask <span class="channel">#sysops</span> or
22
+ <span class="channel">#devtools</span>
23
+ to add you to the <span class="the-group">deploy-prod</span> LDAP group.
24
+ </div>
25
+ <script>$('#info_msg_report').show();</script>
26
+ {{/ allowed_to_push_to_prod?}}
27
+
28
+ </div>
29
+
@@ -0,0 +1,15 @@
1
+ <ul id="run-log">
2
+ {{# files}}
3
+ <li>
4
+ <span class="timestamp-normal">{{time}}</span>
5
+ <a href="/run_logs/view/{{name}}">{{name}}</a>
6
+ </li>
7
+ {{/ files}}
8
+ </ul>
9
+
10
+ {{#next_page }}
11
+ <a href="/run_logs?page={{ to_s }}">More run logs</a>
12
+ {{/next_page}}
13
+ {{^next_page}}
14
+ No more run logs
15
+ {{/next_page}}
@@ -0,0 +1,8 @@
1
+ <form>
2
+ <div>
3
+ <label>
4
+ <input type="checkbox" id="auto_scroll" checked="checked">
5
+ Auto scroll command output?
6
+ </label>
7
+ </div>
8
+ </form>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link rel="stylesheet" href="/static/css/style.css?v=10" type="text/css" media="screen">
5
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
6
+ <style type="text/css" media="screen">
7
+ body { background:#111 none repeat scroll 0 0; }
8
+ </style>
9
+ </head>
10
+ <body class='code'>
11
+ {{ yield }}
12
+ </body>
13
+ </html>
@@ -0,0 +1,3 @@
1
+ module Deployinator
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ require 'deployinator/helpers/deploy'
2
+ require 'json'
3
+
4
+ module Deployinator::Views
5
+ class DeploysStatus < Layout
6
+ include Deployinator::Helpers::DeployHelpers
7
+
8
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/deploys_status.mustache"
9
+
10
+ def current_deploys
11
+ ret = []
12
+ JSON.parse(get_list_of_deploys.to_json).each do |deploy|
13
+ ret << { "stack" => deploy['stack'], "stage" => deploy['stage'] }
14
+ end
15
+ if (ret.length>0)
16
+ ret
17
+ else
18
+ { "stack" => "alcohol", "stage" => "consuming" }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Deployinator::Views
2
+ class Index < Layout
3
+
4
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/index.mustache"
5
+
6
+ # Public: Gets an array of stacks for use in templating the
7
+ # index page.
8
+ #
9
+ # Retuns an array of non-pinned stacks!
10
+ def get_other_stack_list
11
+ Deployinator.get_stacks
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'deployinator/helpers/git'
2
+ require 'deployinator/helpers/stack-tail'
3
+
4
+ module Deployinator
5
+ module Views
6
+ class Layout < Mustache
7
+ include Deployinator::Helpers::GitHelpers,
8
+ Deployinator::Helpers::StackTailHelpers,
9
+ Deployinator::Helpers::VersionHelpers
10
+
11
+ @@internal_partials = ["log", "log_table", "generic_single_push", "scroll_control", "messageboxes"]
12
+
13
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/layout.mustache"
14
+
15
+ def self.partial(name)
16
+ if @@internal_partials.include?(name.to_s)
17
+ File.read("#{File.dirname(__FILE__)}/../templates/#{name.to_s}.mustache")
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ def set_stack(stack)
24
+ @stack = stack
25
+ end
26
+
27
+ def disabled_override
28
+ @disabled_override
29
+ end
30
+
31
+ def additional_bottom_body_html
32
+ ""
33
+ end
34
+
35
+ def additional_top_body_html
36
+ ""
37
+ end
38
+
39
+ def additional_header_html
40
+ ""
41
+ end
42
+
43
+ def tailer_loading_message
44
+ "Currently connecting to tailer web socket. If this message persists for a long time, please contact your administrator. If you are developing a new stack, try restarting the deployinator-tailer."
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ module Deployinator::Views
2
+ class Log < Layout
3
+
4
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/log.mustache"
5
+
6
+ def log_lines
7
+ @params = @params.inject({}) {|p,(k,v)| p[k.intern] = v; p }
8
+ puts @params
9
+ log_to_hash({:no_limit => true}.merge(@params))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ module Deployinator::Views
2
+ class LogTable < Layout
3
+
4
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/log_table.mustache"
5
+
6
+ def log_lines
7
+ @params = @params.inject({}) {|p,(k,v)| p[k.intern] = v; p }
8
+ # this on is called from /log
9
+ log_to_hash({:no_limit => true, :page => 1}.merge(@params))
10
+ end
11
+
12
+ def dashboards?
13
+ false
14
+ end
15
+
16
+ def show_counts?
17
+ @params[:show_counts] == "true"
18
+ end
19
+
20
+ def prev_page
21
+ return unless @params && @params[:page]
22
+ page = @params[:page].to_i
23
+ if page && page > 1
24
+ page - 1
25
+ else
26
+ false
27
+ end
28
+ end
29
+
30
+ def next_page
31
+ page = @params[:page] ? @params[:page].to_i : 1
32
+ page + 1
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ module Deployinator::Views
2
+ class RunLogs < Layout
3
+
4
+ self.template_file = "#{File.dirname(__FILE__)}/../templates/run_logs.mustache"
5
+
6
+ PER_PAGE = 30
7
+
8
+ # Internal: determines what the next page number is.
9
+ #
10
+ # Returns the next page number
11
+ def next_page
12
+ page = get_page
13
+ num_run_logs = get_run_logs.count
14
+ return (page+1)*PER_PAGE < num_run_logs ? page + 1 : false
15
+ end
16
+
17
+
18
+ # Internal: fetches the run_log files to be displayed in a list view
19
+ #
20
+ # Returns an array of hashes with name, time keys
21
+ def files
22
+ page = get_page
23
+ offset = PER_PAGE * page
24
+ get_run_logs(:limit => PER_PAGE, :offset => offset)
25
+ end
26
+
27
+ def get_page
28
+ @params['page'].to_i || 0
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ require "deployinator"
2
+ require 'deployinator/base'
3
+
4
+ module Deployinator
5
+ class <%= company %>App < Deployinator::DeployinatorApp
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'deployinator'
2
+ require 'deployinator/base'
3
+ require 'lib/app'
4
+ require 'deployinator/logging'
5
+
6
+ Encoding.default_external="UTF-8" if Kernel.const_defined?("Encoding")
7
+
8
+ use Rack::CommonLogger
9
+
10
+ run Deployinator::<%= company %>App.new
@@ -0,0 +1,15 @@
1
+ module Deployinator
2
+ module Helpers
3
+ module <%= mustache_class %>Helpers
4
+ def <%= stack %>_production_version
5
+ # %x{curl http://my-app.com/version.txt}
6
+ "1234567-abc"
7
+ end
8
+
9
+ def <%= stack %>_head_build
10
+ # %x{git ls-remote -h http://www.github.com/name/repo.git origin/master | cut -c1-8.chomp
11
+ "12345678"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'helpers/<%= stack %>'
2
+ module Deployinator
3
+ module Stacks
4
+ class <%= mustache_class %>Deploy < Deployinator::Deploy
5
+ include Deployinator::Helpers::<%= mustache_class %>Helpers
6
+
7
+ def <%= stack %>_production(options={})
8
+ old_build = environments[0][:current_build].call
9
+
10
+ log_and_stream "Fill in the <%= stack %>_production method in stacks/<%= stack %>.rb!<br>"
11
+
12
+ # log the deploy
13
+ log_and_shout :old_build => old_build, :build => environments[0][:next_build].call
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1 @@
1
+ {{< generic_single_push }}
@@ -0,0 +1,7 @@
1
+ require 'deployinator/views/layout'
2
+ require 'helpers/<%= stack %>'
3
+ module Deployinator::Views
4
+ class <%= mustache_class %> < Layout
5
+ include Deployinator::Helpers::<%= mustache_class %>Helpers
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+ require 'deployinator'
2
+ require 'deployinator/helpers'
3
+ require 'deployinator/helpers/dsh'
4
+ require 'test/unit'
5
+ require 'mocha/setup'
6
+
7
+ include Deployinator
8
+ include Deployinator::Helpers
9
+ include Deployinator::Helpers::DshHelpers
10
+
11
+ #
12
+ # Set of tests for methods in our DshHelpers Module
13
+ #
14
+ class DshHelperTest < Test::Unit::TestCase
15
+
16
+ def test_hosts_for_ignores_comments
17
+ DshHelpers.expects(:`).returns("host1\n#host2\nhost3")
18
+ assert_equal(["host1","host3"], DshHelpers.hosts_for("foo"))
19
+ end
20
+
21
+ def test_hosts_for_ignores_comments_whitespace_before
22
+ DshHelpers.expects(:`).returns("host1\n #host2\nhost3")
23
+ assert_equal(["host1","host3"], DshHelpers.hosts_for("hoo"))
24
+ end
25
+
26
+ def test_hosts_for
27
+ DshHelpers.expects(:`).returns("host1\nhost2\nhost3")
28
+ assert_equal(["host1","host2","host3"], DshHelpers.hosts_for("bar"))
29
+ end
30
+
31
+ def test_host_for_raises_when_nil
32
+ DshHelpers.expects(:`).returns("")
33
+ # $? is the return value of the previous backtick command
34
+ # we are mocking it
35
+ $?.expects(:exitstatus).returns(1)
36
+ assert_raises(RuntimeError) do
37
+ DshHelpers.hosts_for("baz")
38
+ end
39
+ end
40
+ end