public
Description: Inter-application integration testing
Homepage:
Clone URL: git://github.com/gma/integral.git
integral / Thorfile
100644 194 lines (165 sloc) 4.89 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
begin
  require "integral"
rescue LoadError
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
  require "integral"
end
 
require "readline"
 
Integral::Database.connect
 
class Db < Thor
  desc "migrate", "migrate the database"
  def migrate
    ActiveRecord::Migration.verbose =
        ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
    ActiveRecord::Migrator.migrate(
        "db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
  end
  
  desc "init", "create first successful test run"
  def init
    run = TestRun.new
    run.application_versions << ApplicationVersion.check_current_versions(:live)
    run.passed = true
    run.save!
  end
end
 
class App < Thor
  desc "list", "show all applications"
  def list
    Application.find(:all, :order => "name").each do |app|
      active = app.active? ? "ACTIVE\t\t" : "(inactive)\t"
      puts "#{active}#{app.name} (#{app.path})"
    end
  end
  
  desc "add NAME PATH", "add an application to be tested"
  def add(name, path)
    app = Application.create(:name => name, :path => path)
    if app.errors.on(:name)
      $stderr.write("ERROR: '#{name}' #{app.errors.on(:name)}\n")
    else
      list
    end
  end
  
  desc "remove NAME", "remove an application (caution!)"
  def remove(name)
    app = Application.find_by_name(name)
    if app
      puts "WARNING: Removing '#{name}' will remove it's history.\n\n"
      puts "You may be better off deactivating it instead:\n\n"
      puts " $ thor integral:app:deactivate #{name}\n\n"
      print "Are you sure you want to remove #{name}? [y/N] "
      response = Readline.readline
      if response =~ /^\s*y/
        app.destroy
        list
      end
    end
  end
  
  desc "activate NAME", "activate an existing application"
  def activate(name)
    app = Application.find_by_name(name)
    app && app.activate!
    list
  end
  
  desc "deactivate NAME", "deactivate an active application "
  def deactivate(name)
    app = Application.find_by_name(name)
    app && app.deactivate!
    list
  end
end
 
module Colourizer
  
  ## These methods were shamelessly stolen from rspec. Sorry rspec.
  
  private
    def colour(text, colour_code)
      return text unless output_to_tty?
      "#{colour_code}#{text}\e[0m"
    end
 
    def output_to_tty?
      begin
        $stdout.tty?
      rescue NoMethodError
        false
      end
    end
    
    def green(text)
      colour(text, "\e[32m")
    end
 
    def red(text)
      colour(text, "\e[31m")
    end
end
 
class Tests < Thor
  include Colourizer
  
  desc "run", "run the integration tests"
  def run
    TestRun.start
  end
  
  desc "recent", "show results of last 5 runs"
  def recent
    runs = TestRun.find(:all,
                        :include => :application_versions,
                        :order => "created_at DESC",
                        :limit => 5)
    runs.reverse!
    puts sprintf("%-40s %s", "Time", "Outcome")
    puts "-" * 78
    runs.each do |run|
      outcome = run.passed ? green("pass") : red("FAIL")
      puts sprintf("%-40s %s", run.created_at, outcome)
    end
  end
end
 
class Versions < Thor
  include Colourizer
  
  desc "staging", "show apps on test server"
  method_options :verbose => :boolean
  def staging
    ENV["VERBOSE"] = "1" if options["verbose"]
    show_versions_on_server(:test)
  end
  
  desc "live", "show apps on live server"
  method_options :verbose => :boolean
  def live
    ENV["VERBOSE"] = "1" if options["verbose"]
    show_versions_on_server(:live)
  end
 
  desc "check APP VERSION", "check whether combination is tested"
  method_options :verbose => :boolean
  def check(name, version)
    versions = check_current_versions(:live).merge(name => version)
    app_version = "#{name} (version #{version})"
    TestRun.passed?(versions) ? success(app_version) : failure(app_version)
  rescue TestRunNotFound
    failure(app_version)
  end
 
  private
    def success(app_version)
      puts green("Success: deployment of #{app_version} has been tested")
    end
    
    def failure(app_version)
      puts red("ERROR: deployment of #{app_version} has not been tested")
      exit(1)
    end
    
    def version_dict(app_versions)
      flattened = app_versions.map do |app_version|
        [app_version.application.name, app_version.version]
      end.flatten
      Hash[*flattened]
    end
  
    def check_current_versions(type)
      app_versions = ApplicationVersion.check_current_versions(type).sort do |a, b|
        a.application.name <=> b.application.name
      end
      version_dict(app_versions)
    end
 
    def dump_versions(app_versions)
      puts sprintf("%-15s %s", "Application", "Version")
      puts "-" * 78
      app_versions.each do |name, version|
        puts sprintf("%-15s %s", name, version)
      end
    end
  
    def show_versions_on_server(type)
      dump_versions(check_current_versions(type))
    end
end