groundcontrol 0.0.1

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.
data/bin/groundcontrol ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'yaml'
5
+ require 'groundcontrol'
6
+
7
+ module GroundControl
8
+
9
+ class Command
10
+
11
+ def self.run
12
+ repositories = YAML.load_file("config/projects.yml")['projects']
13
+ FileUtils.mkdir_p "builds"
14
+
15
+ repositories.each do |project, config|
16
+
17
+ build_task = GroundControl::Builder.new(project, config)
18
+ build_task.build
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ GroundControl::Command.run
@@ -0,0 +1,25 @@
1
+ module GroundControl
2
+
3
+ class BuildReport
4
+
5
+ attr_reader :project_name, :branch, :testunit_success, :cucumber_success, :commit
6
+
7
+ def initialize(project_name, branch, testunit_success, cucumber_success, commit)
8
+ @project_name = project_name
9
+ @branch = branch
10
+ @testunit_success = testunit_success
11
+ @cucumber_success = cucumber_success
12
+ @commit = commit
13
+ end
14
+
15
+ def success?
16
+ testunit_success && cucumber_success
17
+ end
18
+
19
+ def failed?
20
+ !success?
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,165 @@
1
+ require 'rubygems'
2
+ require 'git'
3
+ require 'tinder'
4
+ require 'grit'
5
+ require 'net/http'
6
+
7
+ module GroundControl
8
+
9
+ class Builder
10
+
11
+ def initialize(project_name, config)
12
+ @project_name = project_name
13
+ @config = config
14
+ @workspace = File.join("builds", project_name)
15
+ @build_directory = File.join(@workspace, "build")
16
+ @reports_directory = File.join(@workspace, "reports")
17
+ @git_url = @config['git']
18
+ end
19
+
20
+ def build
21
+ create_workspace()
22
+
23
+ clone_repository()
24
+
25
+ prepare_build_environment()
26
+
27
+ test_report = run_tests_and_report()
28
+
29
+ notify_campfire_of_build_result(test_report, @project_name, @repository)
30
+ end
31
+
32
+ private
33
+
34
+ def notify_campfire_of_build_result(test_report, project_name, repository)
35
+ campfire_config = @config['campfire']
36
+
37
+ campfire = Tinder::Campfire.new campfire_config['subdomain'], :token => campfire_config['token']
38
+ room = campfire.find_room_by_name(campfire_config['room'])
39
+
40
+ last_commit = repository.commits.first
41
+
42
+ if test_report.success?
43
+ room.speak "Build SUCCEEDED. +1 for #{last_commit.author.name}."
44
+ else
45
+ room.speak "Build FAILED for #{project_name}/#{repository.head.name} #{@config['github']}/commit/#{test_report.commit.sha}. #{last_commit.author.name} is definitely not the best developer."
46
+ end
47
+ end
48
+
49
+ def start_virtual_screen
50
+ ENV['DISPLAY'] = ":5"
51
+
52
+ xvfb_pid = fork do
53
+ exec 'Xvfb :5 -ac -screen 0 1024x768x8'
54
+ end
55
+ end
56
+
57
+ def run_unit_tests()
58
+ ENV['CI_REPORTS'] = "../reports/testunit"
59
+
60
+ test_output = `cd #{@build_directory}; bundle exec rake ci:setup:testunit test`
61
+ return $?.to_i
62
+ end
63
+
64
+ def run_cucumber_tests()
65
+ screen_pid = start_virtual_screen()
66
+
67
+ ENV['CUCUMBER_OPTS'] = "--format junit --out ../reports/features"
68
+
69
+ cucumber_output = `cd #{@build_directory}; bundle exec rake cucumber`
70
+ cucumber_status = $?.to_i
71
+
72
+ Process.kill "TERM", screen_pid
73
+
74
+ return cucumber_status
75
+ end
76
+
77
+ def run_tests_and_report()
78
+ testunit_return_code = run_unit_tests()
79
+ cucumber_return_code = run_cucumber_tests()
80
+
81
+ return BuildReport.new(@project_name, @repository.head.name, testunit_return_code == 0, cucumber_return_code == 0, @repository.commits.first)
82
+ end
83
+
84
+ def clone_repository
85
+ Git.clone(@git_url, @build_directory)
86
+ @repository = Grit::Repo.new(@build_directory)
87
+ end
88
+
89
+ def create_workspace
90
+ FileUtils.rm_rf @workspace
91
+
92
+ FileUtils.mkdir_p(@build_directory)
93
+ FileUtils.mkdir_p(@reports_directory)
94
+ end
95
+
96
+ def initialize_rvm
97
+ system "cd #{@build_directory}; rvm rvmrc trust"
98
+ system "cd #{@build_directory}; rvm reload"
99
+ end
100
+
101
+ def install_bundler_gems()
102
+ system "cd #{@build_directory}; bundle install --without production"
103
+ end
104
+
105
+ def inject_ci_reporter()
106
+ doc = <<EOF
107
+ require 'rubygems'
108
+ require 'ci/reporter/rake/test_unit' # use this if you're using Test::Unit
109
+ EOF
110
+
111
+ File.open("#{@build_directory}/lib/tasks/ci_reporter.rake", 'w') { |f| f.write(doc) }
112
+ end
113
+
114
+ def inject_database_config()
115
+
116
+ database = <<EOF
117
+ test: &test
118
+ adapter: mysql2
119
+ encoding: utf8
120
+ reconnect: false
121
+ database: #{@project_name}_test
122
+ pool: 5
123
+ username: root
124
+ password:
125
+
126
+ cucumber:
127
+ <<: *test
128
+ EOF
129
+
130
+ File.open("#{@build_directory}/config/database.yml", 'w') { |f| f.write(database) }
131
+
132
+ end
133
+
134
+ def load_empty_schema()
135
+ system "cd #{@build_directory}; bundle exec rake db:schema:load"
136
+ end
137
+
138
+ def setup_database()
139
+ inject_database_config()
140
+ load_empty_schema()
141
+ end
142
+
143
+ def inject_thinking_sphinx_config
144
+ sphinx_config = <<EOF
145
+ test:
146
+ port: 9312
147
+ EOF
148
+
149
+ File.open("#{@build_directory}/config/sphinx.yml", 'w') { |f| f.write(sphinx_config) }
150
+ end
151
+
152
+ def prepare_build_environment
153
+ ENV['RAILS_ENV'] = "test"
154
+
155
+ initialize_rvm()
156
+ install_bundler_gems()
157
+ inject_ci_reporter()
158
+
159
+ setup_database()
160
+ inject_thinking_sphinx_config()
161
+ end
162
+
163
+ end
164
+
165
+ end
@@ -0,0 +1,46 @@
1
+ require "nokogiri"
2
+
3
+ module GroundControl
4
+
5
+ class TestResult
6
+
7
+ attr_reader :name, :message
8
+
9
+ def self.read_from_xml(xml_string)
10
+ doc = Nokogiri::XML.parse(xml_string)
11
+ tests = []
12
+
13
+ doc.xpath('//testcase').each do |testcase|
14
+ failure = testcase.xpath('//failure')
15
+ if failure.blank?
16
+ tests << TestResult.new(testcase['name'])
17
+ else
18
+ tests << TestResult.new(testcase['name'], failure.first.content)
19
+ end
20
+ end
21
+
22
+
23
+ return tests
24
+ end
25
+
26
+ def initialize(name, failure_message = nil)
27
+ @name = name
28
+ @failed = false
29
+
30
+ if failure_message
31
+ @failed = true
32
+ @message = failure_message
33
+ end
34
+ end
35
+
36
+ def failed?
37
+ return @failed
38
+ end
39
+
40
+ def success?
41
+ return true if not @failed
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,3 @@
1
+ require "groundcontrol/builder"
2
+ require "groundcontrol/build_report"
3
+ require "groundcontrol/test_result"
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: groundcontrol
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Michiel Sikkes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-12-15 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: grit
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: git
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: tinder
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: nokogiri
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :runtime
59
+ version_requirements: *id004
60
+ description: Groundcontrol powers test builds for Rails projects
61
+ email: michiel@firmhouse.com
62
+ executables:
63
+ - groundcontrol
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - lib/groundcontrol.rb
70
+ - lib/groundcontrol/builder.rb
71
+ - lib/groundcontrol/build_report.rb
72
+ - lib/groundcontrol/test_result.rb
73
+ - bin/groundcontrol
74
+ has_rdoc: true
75
+ homepage: http://github.com/Firmhouse/groundcontrol
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.6.2
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Runs automated Rails tests and reports back.
102
+ test_files: []
103
+