cuke_ci_workers 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.
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'erb'
4
+ require 'optparse'
5
+
6
+ def file_from_template(name, dest, project_id, api_key)
7
+ File.open(dest, 'w') do |f|
8
+ f.puts(render_template(name, project_id, api_key))
9
+ end
10
+ end
11
+
12
+ def render_template(name, project_id, api_key)
13
+ file_name = File.expand_path("../../templates/#{name}.erb", __FILE__)
14
+ erb = ERB.new(File.read(file_name))
15
+ erb.result(binding)
16
+ end
17
+
18
+ options = {}
19
+ options[:hook] = nil
20
+ options[:runner] = false
21
+
22
+ opts = OptionParser.new do |opts|
23
+ opts.banner = "Usage: [options] PROJECT_ID API_KEY"
24
+
25
+ opts.on "--runner-config", "Install runner config" do
26
+ options[:runner_config] = true
27
+ end
28
+
29
+ opts.on "--post-commit", "Install post commit hook" do
30
+ options[:hook] = 'post-commit'
31
+ end
32
+
33
+ opts.on "--post-receive", "Install post receive hook" do
34
+ options[:hook] = 'post-receive'
35
+ end
36
+ end
37
+
38
+ begin
39
+ opts.parse!
40
+ rescue
41
+ puts opts.help
42
+ exit
43
+ end
44
+
45
+ if ARGV.length != 2
46
+ puts opts.help
47
+ else
48
+ api_key = ARGV.pop
49
+ project_id = ARGV.pop
50
+
51
+ if options[:hook]
52
+ performed = false
53
+
54
+ %w(.git/hooks hooks).each do |dir|
55
+ hook_file_name = File.join(dir, options[:hook])
56
+
57
+ if File.exists?(dir)
58
+ file_from_template(options[:hook], hook_file_name, project_id, api_key)
59
+ File.chmod(0770, hook_file_name)
60
+
61
+ puts "Hook installed in '#{hook_file_name}'."
62
+ performed = true
63
+ end
64
+ end
65
+
66
+ unless performed
67
+ puts 'Not in a git direcotry. Hook not installed.'
68
+ end
69
+ end
70
+
71
+ if options[:runner_config]
72
+ file_from_template('runner_config.yml', 'cuke_ci_runner_config.yml', project_id, api_key)
73
+ puts 'Runner config installed.'
74
+ end
75
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
+ require 'cuke_ci_workers/runner'
5
+
6
+ CukeCIWorkers::Runner.parse!(ARGV).run
7
+
@@ -0,0 +1,80 @@
1
+
2
+ require 'rubygems'
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+ require 'grit'
7
+
8
+ require 'cuke_ci_workers/worker'
9
+
10
+ module CukeCIWorkers
11
+ class Notifier < Worker
12
+ def initialize(server_url, log_file_name, log_level = nil)
13
+ super(log_file_name, log_level)
14
+ @server_uri = URI.parse(server_url)
15
+ end
16
+
17
+ def post_commit
18
+ json = generate_json_for_head
19
+ push_json(json)
20
+ rescue Exception => e
21
+ log_exception(e)
22
+ end
23
+
24
+ def post_reveive(before_rev, after_rev, ref)
25
+ json = generate_json(before_rev, after_rev, ref)
26
+ push_json(json)
27
+ rescue Exception => e
28
+ log_exception(e)
29
+ end
30
+
31
+ private
32
+
33
+ def push_json(json)
34
+ Net::HTTP.start(@server_uri.host, @server_uri.port) do |http|
35
+ http.post("#{@server_uri.path}?#{@server_uri.query}", json, 'Content-Type' => 'application/json')
36
+ end
37
+ end
38
+
39
+ def generate_json_for_head
40
+ generate_json('HEAD^', 'HEAD', repository.head.name)
41
+ end
42
+
43
+ def generate_json(before_rev, after_rev, ref)
44
+ before = repository.commit(before_rev)
45
+ after = repository.commit(after_rev)
46
+
47
+ {:payload => {
48
+ :before => before.sha,
49
+ :after => after.sha,
50
+ :ref => ref,
51
+ :commits => repository.commits_between(before, after).collect do |commit|
52
+ {
53
+ :id => commit.sha,
54
+ :message => commit.message,
55
+ :timestamp => commit.committed_date.xmlschema,
56
+ :url => '',
57
+ :added => [],
58
+ :removed => [],
59
+ :modified => [],
60
+ :author => {
61
+ :name => commit.author.name,
62
+ :email => commit.author.email
63
+ }
64
+ }
65
+ end,
66
+ }
67
+ }.to_json
68
+ end
69
+
70
+ def repository
71
+ Grit::Repo.new(".")
72
+ end
73
+
74
+ class << self
75
+ def parse!(args)
76
+ Notifier.new(*args)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,167 @@
1
+
2
+ require 'rubygems'
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+ require 'optparse'
7
+ require 'fileutils'
8
+ require 'yaml'
9
+ require 'logger'
10
+
11
+ require 'cuke_ci_workers/worker'
12
+
13
+ module CukeCIWorkers
14
+ class Runner < Worker
15
+ def initialize(options)
16
+ @configuration_file_name = options[:configuration_file_name]
17
+ @configuration = YAML.load_file(@configuration_file_name)
18
+
19
+ @poll_uri = URI.parse(@configuration['poll_url'])
20
+ @push_url = @configuration['push_url']
21
+
22
+ @verbose = options[:verbose]
23
+
24
+ super(@configuration['log_file_name'], @configuration['log_level'])
25
+ end
26
+
27
+ def run
28
+ $running = true
29
+ Signal.trap('INT') { $running = false }
30
+
31
+ while($running) do
32
+ begin
33
+ run_present = poll_for_run
34
+ #rescue Exception => e
35
+ # log_exception(e)
36
+ end
37
+
38
+ if run_present
39
+ begin
40
+ pull_repo
41
+ checkout_commit
42
+ prepare
43
+
44
+ if result = cucumber
45
+ push_result(result)
46
+ else
47
+ push_error
48
+ end
49
+ #rescue Exception => e
50
+ # log_exception(e)
51
+ end
52
+ else
53
+ sleep 5
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def poll_for_run
61
+ message('Polling for run')
62
+ result = Net::HTTP.get(@poll_uri)
63
+
64
+ begin
65
+ hash = JSON.parse(result)
66
+ rescue JSON::ParserError
67
+ hash = {}
68
+ end
69
+
70
+ @commit_hash = hash['commit_hash']
71
+ @run_id = hash['id']
72
+
73
+ @commit_hash
74
+ end
75
+
76
+ def pull_repo
77
+ message("Pulling repository")
78
+ run_command(:pull)
79
+ end
80
+
81
+ def checkout_commit
82
+ message("Checking out #{@commit_hash}")
83
+ run_command(:check_out, @commit_hash)
84
+ end
85
+
86
+ def prepare
87
+ message('Preparing working directory')
88
+ return
89
+ run_command(:prepare)
90
+ end
91
+
92
+ def cucumber
93
+ message('Running Cucumber')
94
+ output = run_command(:cucumber, temp_file_name)
95
+
96
+ if $?.success?
97
+ File.read(temp_file_name)
98
+ else
99
+ logger.error("Cucumber failed: #{output}")
100
+ nil
101
+ end
102
+ end
103
+
104
+ def push_result(result)
105
+ message('Pushing results')
106
+ logger.info "Pushing result: #{result}"
107
+
108
+ json = "{'payload': #{result}}"
109
+
110
+ push_json(json)
111
+ end
112
+
113
+ def push_error
114
+ message('Pushing error')
115
+ json = "{'error': 'Cucumber did not complete successfully.'}"
116
+ logger.info "Pushing error: #{json}"
117
+
118
+ push_json(json)
119
+ end
120
+
121
+ def push_json(json)
122
+ url = @push_url % @run_id
123
+ @push_uri = URI.parse(url)
124
+
125
+ message "Pushing json to #{url}"
126
+
127
+ Net::HTTP.start(@push_uri.host, @push_uri.port) do |http|
128
+ http.post("#{@push_uri.path}?#{@push_uri.query}", json, 'Content-Type' => 'application/json')
129
+ end
130
+ end
131
+
132
+ def temp_file_name
133
+ @configuration['temp_file_name']
134
+ end
135
+
136
+ class << self
137
+ def parse!(args)
138
+ default_runner_config_file_name = './cuke_ci_runner_config.yml'
139
+ options = {}
140
+
141
+ opts = OptionParser.new do |opts|
142
+ opts.banner = 'Usage: ...'
143
+
144
+ opts.on("-c", "--configuration CONFIGURATION_FILE_NAME", "Path to configuration file. Defaults to '#{default_runner_config_file_name}'.") do |file_name|
145
+ options[:configuration_file_name] = file_name
146
+ end
147
+
148
+ opts.on("-v", "--verbose", "Be verbose") do |v|
149
+ options[:verbose] = true
150
+ end
151
+
152
+ opts.on_tail("-h", "--help", "Show this message") do
153
+ puts opts
154
+ exit
155
+ end
156
+ end
157
+ opts.parse!
158
+
159
+ options[:configuration_file_name] ||= default_runner_config_file_name
160
+ self.new(options)
161
+ rescue OptionParser::ParseError
162
+ puts opts
163
+ exit
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'logger'
7
+
8
+ module CukeCIWorkers
9
+ class Worker
10
+ attr_accessor :logger
11
+
12
+ def initialize(log_file_name, log_level = nil)
13
+ @logger = Logger.new(log_file_name)
14
+ @logger.level = Logger.const_get(log_level) rescue Logger::INFO
15
+ end
16
+
17
+ private
18
+
19
+ def log_exception(e)
20
+ logger.error(e.message + "\n " + e.backtrace * "\n ")
21
+ end
22
+
23
+ def message(text)
24
+ logger.info text
25
+ if @verbose
26
+ puts("========= #{text} =========")
27
+ end
28
+ end
29
+
30
+ def run_command(key, *args)
31
+ command = interpolate_command(key, args)
32
+ logger.info " #{command}"
33
+
34
+ if @verbose
35
+ puts command
36
+ `#{command}`
37
+ else
38
+ `#{command} 2> /dev/null`
39
+ end
40
+ end
41
+
42
+ def interpolate_command(key, args)
43
+ command = @configuration['commands'][key.to_s]
44
+ command % args
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/ruby
2
+
3
+ server_url = 'http://localhost:3000/projects/1/receipt?api_key=3d177538439c92c8d278208ff1ae098f'
4
+ log_file_name = 'cuke_ci_notifier.log'
5
+
6
+ require 'rubygems'
7
+ require 'cuke_ci_workers/notifier'
8
+ # require '/home/tim/code/rr10/rr10-team-179/cucumber-ci-workers/lib/cuke_ci_workers/notifier'
9
+
10
+ CukeCIWorkers::Notifier.new(server_url, log_file_name).post_commit
11
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ server_url = 'http://localhost:3000/projects/<%= project_id %>/receipt?api_key=<%= api_key %>'
4
+ log_file_name = 'cuke_ci_notifier.log'
5
+
6
+ require 'rubygems'
7
+ require 'cuke_ci_workers/notifier'
8
+
9
+ CukeCIWorkers::Notifier.new(server_url, log_file_name).post_commit
10
+
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/ruby
2
+
3
+ server_url = 'http://localhost:3000/project/1/receipt'
4
+ log_file_name = 'cuke_ci_notifier.log'
5
+
6
+ require 'rubygems'
7
+ require 'cuke_ci_workers/notifier'
8
+
9
+ CukeCIWorkers::Notifier.new(server_url, log_file_name).post_reveice(*ARGV)
@@ -0,0 +1,10 @@
1
+ temp_file_name: "cucumber.out"
2
+ log_file_name: "cuke_ci_runner.log"
3
+ log_level: "WARN"
4
+ poll_url: "http://localhost:3000/projects/<%= project_id %>/runs/next?api_key=<%= api_key %>"
5
+ push_url: "http://localhost:3000/projects/<%= project_id %>/runs/%s/results?api_key=<%= api_key %>"
6
+ commands:
7
+ pull: "git pull origin master"
8
+ check_out: "git reset --hard %s"
9
+ prepare: "rake db:reset"
10
+ cucumber: "cucumber --format json --out %s"
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cuke_ci_workers
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Gregor Weckbecker
13
+ - Vangelis Tsoumenis
14
+ - Tim Fischbach
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-17 00:00:00 +02:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: Cucumber based continuous integration.
24
+ email:
25
+ - info@timfischbach.de
26
+ executables:
27
+ - cuke_ci_runner
28
+ - cuke_ci_install
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - bin/cuke_ci_runner
35
+ - bin/cuke_ci_install
36
+ - lib/cuke_ci_workers/worker.rb
37
+ - lib/cuke_ci_workers/runner.rb
38
+ - lib/cuke_ci_workers/notifier.rb
39
+ - templates/post-commit
40
+ - templates/runner_config.yml.erb
41
+ - templates/post-commit.erb
42
+ - templates/post-receive
43
+ has_rdoc: true
44
+ homepage: http://whiteboard.r10.railsrumble.com/
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 23
67
+ segments:
68
+ - 1
69
+ - 3
70
+ - 6
71
+ version: 1.3.6
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.7
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Runner and notifier tool for CukeCI.
79
+ test_files: []
80
+