omg_pull_request 0.0.6

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 (42) hide show
  1. data/.gitignore +47 -0
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +68 -0
  4. data/LICENSE +22 -0
  5. data/README.md +66 -0
  6. data/Rakefile +12 -0
  7. data/bin/omg_pull_request +13 -0
  8. data/lib/omg_pull_request.rb +32 -0
  9. data/lib/omg_pull_request/aws/store.rb +30 -0
  10. data/lib/omg_pull_request/configuration.rb +55 -0
  11. data/lib/omg_pull_request/context.rb +29 -0
  12. data/lib/omg_pull_request/git_client.rb +31 -0
  13. data/lib/omg_pull_request/github_wrapper.rb +50 -0
  14. data/lib/omg_pull_request/lolcommits.rb +39 -0
  15. data/lib/omg_pull_request/notifications.rb +66 -0
  16. data/lib/omg_pull_request/prowl.rb +77 -0
  17. data/lib/omg_pull_request/test_logger.rb +20 -0
  18. data/lib/omg_pull_request/test_runner.rb +22 -0
  19. data/lib/omg_pull_request/test_runner/base.rb +128 -0
  20. data/lib/omg_pull_request/test_runner/rails.rb +19 -0
  21. data/lib/omg_pull_request/test_runner/ruby.rb +9 -0
  22. data/lib/omg_pull_request/version.rb +3 -0
  23. data/locales/en.yml +23 -0
  24. data/locales/omg.yml +20 -0
  25. data/omg_pull_request.gemspec +26 -0
  26. data/test/fixtures/comments +431 -0
  27. data/test/fixtures/config.yml +20 -0
  28. data/test/fixtures/create_comment +24 -0
  29. data/test/fixtures/github_commits +183 -0
  30. data/test/fixtures/kenmazaika +30 -0
  31. data/test/fixtures/pull_requests +151 -0
  32. data/test/mocks/git_client.rb +6 -0
  33. data/test/mocks/pull_request.rb +38 -0
  34. data/test/omg_pull_request/.gitkeep +0 -0
  35. data/test/test_helper.rb +53 -0
  36. data/test/units/omg_pull_request/aws/store_test.rb +22 -0
  37. data/test/units/omg_pull_request/github_wrapper_test.rb +43 -0
  38. data/test/units/omg_pull_request/lolcommits_test.rb +42 -0
  39. data/test/units/omg_pull_request/notifications_test.rb +125 -0
  40. data/test/units/omg_pull_request/prowl_test.rb +51 -0
  41. data/test/units/omg_pull_request/test_runner/base_test.rb +58 -0
  42. metadata +183 -0
data/.gitignore ADDED
@@ -0,0 +1,47 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
16
+ .DS_Store
17
+ *.rb.pid
18
+
19
+ # Assets are precompiled on deploy
20
+ /public/assets
21
+
22
+ # Coverage directory should not be checked in
23
+ /coverage
24
+
25
+ # PEOPLE WHO USE VIM ROCK!
26
+ *.swp
27
+ *.swo
28
+ .swp
29
+ .swo
30
+ *.swn
31
+ *.swm
32
+
33
+ test/functional/coverage/**
34
+ test/unit/coverage/**
35
+ test/functional/advertisers/coverage/**
36
+ .cache_rake_t
37
+ .idea/**
38
+ public/system
39
+ .sass-cache
40
+
41
+ # Allow using Turn for testing, but don't check in configuration
42
+ config/initializers/turn.rb
43
+ config/initializers/error_mass_assign.rb
44
+ config/initializers/activeresource_debug.rb
45
+ tags
46
+ .rbenv-version
47
+ test/omg_pull_request/config.yml
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'minitest'
7
+ gem 'fakeweb'
8
+ gem 'mocha'
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ omg_pull_request (0.0.6)
5
+ activesupport (>= 3.2.8)
6
+ aws-s3 (>= 0.6.3)
7
+ faraday (>= 0.8.4)
8
+ github_api (>= 0.6.5)
9
+ i18n (>= 0.6.0)
10
+ rake (>= 0.9.2.2)
11
+ uuid (>= 2.3.5)
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ activesupport (3.2.8)
17
+ i18n (~> 0.6)
18
+ multi_json (~> 1.0)
19
+ aws-s3 (0.6.3)
20
+ builder
21
+ mime-types
22
+ xml-simple
23
+ builder (3.0.0)
24
+ fakeweb (1.3.0)
25
+ faraday (0.8.4)
26
+ multipart-post (~> 1.1)
27
+ github_api (0.6.5)
28
+ faraday (~> 0.8.1)
29
+ hashie (~> 1.2.0)
30
+ multi_json (~> 1.3)
31
+ nokogiri (~> 1.5.2)
32
+ oauth2
33
+ hashie (1.2.0)
34
+ httpauth (0.1)
35
+ i18n (0.6.0)
36
+ jwt (0.1.5)
37
+ multi_json (>= 1.0)
38
+ macaddr (1.6.1)
39
+ systemu (~> 2.5.0)
40
+ metaclass (0.0.1)
41
+ mime-types (1.19)
42
+ minitest (3.3.0)
43
+ mocha (0.11.4)
44
+ metaclass (~> 0.0.1)
45
+ multi_json (1.3.6)
46
+ multipart-post (1.1.5)
47
+ nokogiri (1.5.5)
48
+ oauth2 (0.8.0)
49
+ faraday (~> 0.8)
50
+ httpauth (~> 0.1)
51
+ jwt (~> 0.1.4)
52
+ multi_json (~> 1.0)
53
+ rack (~> 1.2)
54
+ rack (1.4.1)
55
+ rake (0.9.2.2)
56
+ systemu (2.5.2)
57
+ uuid (2.3.5)
58
+ macaddr (~> 1.0)
59
+ xml-simple (1.1.1)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ fakeweb
66
+ minitest
67
+ mocha
68
+ omg_pull_request!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ken Mazaika
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ ## Omg! Pull Request!
2
+
3
+ Omg! Pull Request! is a daemon designed to easily run automated tests for a project that is hosted on GitHub on the submission of a pull request. On completion of the tests the daemon will make a comment on the pull request on the status of the test suite.
4
+
5
+ #### Goals
6
+
7
+ * Allow simple configuration for a standard rails project
8
+ * Support flexibilty and extensibility to work in non ruby/rails projects
9
+ * Reduce test failures caused by merging in code with broken tests
10
+
11
+ #### Non Goals
12
+
13
+ * Work with non-github environments
14
+
15
+
16
+ ### Integrations
17
+
18
+ The project integrates with a number of third party services to maximize usefulness / coolness.
19
+
20
+ #### Prowl
21
+
22
+ Prowl integration allows you to setup a phone to be alerted when the test suite completes. You will be alerted if you are the author, or have commited in the pull request.
23
+
24
+ #### Lolcommits
25
+
26
+ On running the test suite an animated gif can be generated of the lolcommits that were generated by the pull request. This feature was added for the lulz.
27
+
28
+ ## Installation
29
+
30
+ 1. In a rails project, add `omg_pull_request` to the Gemfile.
31
+ 2. Make an `omg_pull_request` directory in the project's `test` directory.
32
+ 3. Add a `database.yml` file in the `omg_pull_request` dir. This will drop databases, so it is suggested this points to different databases than the main `config/database.yml` file
33
+ 4. Create a github user to run the tests as. This user will need to have access to the repo the test is run on. It can be your developer account, or a new account specifically for this.
34
+ 5. Add a `config.yml` file in the `omg_pull_request` dir. It follows this template:
35
+
36
+ ```
37
+ repo_owner: kenmazaika
38
+ repo: pictures
39
+ locale: en
40
+ runner: Rails
41
+
42
+ github_credentials:
43
+ login: github_user
44
+ password: github_password
45
+
46
+ aws:
47
+ access_token: s3_token
48
+ secret_token: s3_secret
49
+ bucket: s3_bucket
50
+
51
+ prowl:
52
+ application: wherebot
53
+ keys:
54
+ kenmazaika: key
55
+ kenmazaika@gmail.com: key
56
+ ```
57
+
58
+ This is a sample config, with sensitive data scrubbed for running tests on the repo: https://github.com/kenmazaika/pictures. One important note is for the prowl integration it should contain a key for both the github user_name and the email address that can be pulled from git.
59
+
60
+ 6. On a server someplace clone the repo. This cloned repo will be managed by the daemon, and the tests will run on it from now on.
61
+ 7. In a screen session run `omg_pull_request`.
62
+ 8. Enjoy.
63
+
64
+ ### Example
65
+
66
+ You can see an example of a successful pull request that has been `omg_pull_request`ified here: https://github.com/where/omg_pull_request/pull/1.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ require 'rake/clean'
3
+ require 'rake/testtask'
4
+
5
+ include Rake::DSL
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.pattern = 'test/**/*_test.rb'
9
+ end
10
+ task :default => [:test]
11
+
12
+
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'omg_pull_request'
4
+
5
+ include OmgPullRequest
6
+ locale_dir = File.expand_path("../../locales", __FILE__)
7
+ I18n.load_path = [
8
+ File.join(locale_dir, "omg.yml"),
9
+ File.join(locale_dir, "en.yml")
10
+ ]
11
+ I18n.locale = CONFIGURATION.locale if CONFIGURATION.locale
12
+
13
+ TestRunner.start_daemon
@@ -0,0 +1,32 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require 'active_support/all'
4
+ require 'faraday'
5
+ require 'github_api'
6
+ require 'yaml'
7
+ require 'uuid'
8
+ require 'aws/s3'
9
+ require 'i18n'
10
+ require 'omg_pull_request/configuration'
11
+ require 'omg_pull_request/test_logger'
12
+ require 'omg_pull_request/aws/store'
13
+ require 'omg_pull_request/github_wrapper'
14
+ require 'omg_pull_request/notifications'
15
+ require 'omg_pull_request/test_runner'
16
+ require 'omg_pull_request/test_runner/base'
17
+ require 'omg_pull_request/test_runner/rails'
18
+ require 'omg_pull_request/test_runner/ruby'
19
+ require 'omg_pull_request/context'
20
+ require 'omg_pull_request/git_client'
21
+ require 'omg_pull_request/prowl'
22
+ require 'omg_pull_request/lolcommits'
23
+ require 'omg_pull_request/version'
24
+
25
+ module OmgPullRequest
26
+ CONFIGURATION = Configuration.new
27
+ STORE = Aws::Store.new(:storage_config => CONFIGURATION.aws.symbolize_keys)
28
+ CONTEXT = Context.new
29
+ GITHUB_WRAPPER = GithubWrapper.new(:configuration => CONFIGURATION)
30
+ end
31
+
32
+
@@ -0,0 +1,30 @@
1
+ module OmgPullRequest
2
+ module Aws
3
+ class Store
4
+ attr_accessor :storage_config
5
+ def initialize(attributes={})
6
+ attributes.each do |attr, value|
7
+ self.send("#{attr}=", value)
8
+ end
9
+
10
+ AWS::S3::Base.establish_connection!(
11
+ :access_key_id => access_token,
12
+ :secret_access_key => secret_token
13
+ )
14
+ end
15
+
16
+ def store(data, file_name)
17
+ AWS::S3::S3Object.store(file_name, data, bucket, :access => :public_read)
18
+ "http://s3.amazonaws.com/#{bucket}/#{file_name}"
19
+ end
20
+
21
+ private
22
+
23
+ [:access_token, :secret_token, :bucket].each do |attr|
24
+ define_method attr do
25
+ storage_config[attr]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
1
+ module OmgPullRequest
2
+ class Configuration
3
+ attr_reader :config
4
+
5
+ def initialize(attributes={})
6
+ attributes.each do |attr, value|
7
+ self.send("#{attr}=", value)
8
+ end
9
+ @config = YAML.load(File.open(self.config_file))
10
+ end
11
+
12
+
13
+ [:repo_owner, :repo, :database_yml, :aws, :github_credentials,
14
+ :lolcommits_server_url, :prowl, :locale].each do |attr|
15
+ define_method attr do
16
+ self.config[attr.to_s]
17
+ end
18
+ end
19
+
20
+ def local_repo
21
+ self.config['local_repo'] || Dir.pwd
22
+ end
23
+
24
+ def database_yml
25
+ self.config['database_yml'] || File.join(omg_dir, 'database.yml')
26
+ end
27
+
28
+ def config_file
29
+ file = ENV['yml'] || File.join(omg_dir, 'config.yml')
30
+ unless File.exist?(file)
31
+ raise "Configuration file does not exist: #{file}"
32
+ end
33
+
34
+ file
35
+ end
36
+
37
+ def omg_dir
38
+ File.join(Dir.pwd, 'test/omg_pull_request')
39
+ end
40
+
41
+ def runner_class
42
+ "OmgPullRequest::TestRunner::#{config['runner'] || 'Rails'}".constantize
43
+ end
44
+
45
+ module Helpers
46
+ def delegate_config_to(config, *attrs)
47
+ attrs.each do |attr|
48
+ define_method attr do
49
+ self.send(config).send(attr)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ module OmgPullRequest
2
+ class Context
3
+ def ran(request_sha)
4
+ ran_hash[request_sha] = true
5
+ end
6
+
7
+ def ran?(request_sha)
8
+ ran_hash[request_sha] == true
9
+ end
10
+
11
+ def get_animated_shas(issue_number)
12
+ animated_shas[issue_number] || []
13
+ end
14
+
15
+ def add_animated_shas(issue_number, shas)
16
+ animated_shas[issue_number] = get_animated_shas(issue_number) + shas
17
+ end
18
+
19
+ private
20
+
21
+ def ran_hash
22
+ @ran_hash ||= Hash.new
23
+ end
24
+
25
+ def animated_shas
26
+ @animated_sha || Hash.new
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ module OmgPullRequest
2
+ class GitClient
3
+ attr_accessor :logger, :configuration
4
+
5
+ def initialize(attributes=Hash.new)
6
+ attributes.each do |attr, value|
7
+ self.send("#{attr}=", value)
8
+ end
9
+ end
10
+
11
+ def committers(from_sha, to_sha)
12
+ `cd #{local_repo} && git shortlog -sne #{from_sha}..#{to_sha} | awk '{ print $NF}' | cut -d'<' -f2 | cut -d'>' -f1`.split
13
+ end
14
+
15
+ def checkout!(sha)
16
+ logger.log `cd #{local_repo} && git reset --hard && git fetch && git checkout #{sha}`
17
+ end
18
+
19
+ def merge!(sha)
20
+ merge_response = `cd #{local_repo} && git merge #{sha}`
21
+ self.logger.log merge_response
22
+ merge_response.match(/CONFLICT/) ? :conflict : :success
23
+ end
24
+
25
+
26
+ private
27
+
28
+ extend Configuration::Helpers
29
+ delegate_config_to(:configuration, :local_repo)
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module OmgPullRequest
2
+ class GithubWrapper
3
+ attr_accessor :configuration
4
+
5
+ def initialize(attributes={})
6
+ attributes.each do |attr, value|
7
+ self.send("#{attr}=", value)
8
+ end
9
+ end
10
+
11
+ def author_logins(pull_request)
12
+ [pull_request.user.login, github_client.users.get(:user => pull_request.user.login).email]
13
+ end
14
+
15
+ def all_logins(pull_request)
16
+ logins = [pull_request.user.login]
17
+
18
+ logins |= github_client.issues.comments.list(repo_owner, repo, pull_request.number).collect do |c|
19
+ c.user.login
20
+ end
21
+
22
+ logins.uniq
23
+ end
24
+
25
+ def commit_shas(pull_request)
26
+ commits = github_client.pull_requests.commits(repo_owner, repo, pull_request.number)
27
+
28
+ commits.collect do |commit|
29
+ commit.sha[0..10]
30
+ end
31
+ end
32
+
33
+ def make_comment(issue_number, body)
34
+ github_client.issues.comments.create(repo_owner, repo, issue_number, :body => body)
35
+ end
36
+
37
+ def pull_requests
38
+ github_client.pull_requests.list(repo_owner, repo)
39
+ end
40
+
41
+ private
42
+
43
+ extend Configuration::Helpers
44
+ delegate_config_to(:configuration, :repo_owner, :repo, :github_credentials)
45
+
46
+ def github_client
47
+ @github_client ||= Github.new(github_credentials.symbolize_keys)
48
+ end
49
+ end
50
+ end