fight_club 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f2a889515d722593c0bf07deb6a4d972ee78690
4
+ data.tar.gz: 7bcbbb325571b3c77137f36f8fd5941bb4261e08
5
+ SHA512:
6
+ metadata.gz: c93ce8b6ade219c9a773a864c1ef9bda730c5ac78267ba939deac1ef1973265a6365fc7990e5fb325359424a63997e1a9d680a1ac401440f111e40dee0991527
7
+ data.tar.gz: a168e79d03539b657c38e2646d5f41e49eda23357386d44e3255b70e547fb88b6e15f28e7f88b53566777d3e65c25e6a6b5e5ff6c55992995183c4d1b52d776c
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fight-club.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Tim Minkov
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.
@@ -0,0 +1,47 @@
1
+ # FightClub
2
+ ![FightClub]
3
+ (http://i.imgur.com/sQJNhBi.gif)
4
+
5
+ Fight Club will notify users of pull requests of any conflicts against other open pull requests.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'fight-club'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install fight-club
20
+
21
+ ## Configuration
22
+
23
+ Add the following to an initializer in your codebase (`config/initializers/fight_club.rb` in Rails):
24
+
25
+ ```ruby
26
+ FightClub.configure do |config|
27
+ config.repo = 'baxterthehacker/public-repo' # the repo with org/user name
28
+ config.oauth = '12345678901234567890abcdef' # your oauth token
29
+ config.repo_name = 'public-repo' # the repo name alone
30
+ config.uri = 'git@github.com:baxterthehacker/public-repo.git' # the URI to use to clone the repo
31
+ config.master_branch = 'master' # what branch to run fight club against
32
+ end
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Add this to your code:
38
+
39
+ ```ruby
40
+ FightClub.begin(pull_request)
41
+ ```
42
+
43
+ Where `pull_request` looks like a payload from a [Github webhook](https://developer.github.com/v3/pulls/).
44
+
45
+ ## Why?
46
+
47
+ Sometimes you want to move fast! It's annoying to have conflicts with a master branch after another branch gets merged.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fight_club/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fight_club"
8
+ spec.version = FightClub::VERSION
9
+ spec.authors = ["Tim Minkov"]
10
+ spec.email = ["timothyminkov@gmail.com"]
11
+ spec.summary = %q{Finds conflicts against open pull requests}
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.add_development_dependency "bundler", "~> 1.6"
19
+ spec.add_development_dependency "rake"
20
+ spec.add_runtime_dependency "git"
21
+ spec.add_runtime_dependency "octokit"
22
+ spec.add_runtime_dependency "httparty"
23
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "fight_club/version"
2
+ require_relative "fight_club/arena"
3
+ require_relative "fight_club/config"
4
+
5
+ module FightClub
6
+ WORKING_DIR = "#{Dir.pwd}/repos"
7
+
8
+ class << self
9
+ attr_writer :config
10
+ end
11
+
12
+ def self.begin(pull_request)
13
+ Arena.new(pull_request).start
14
+ end
15
+
16
+ def self.config
17
+ @config ||= Config.new
18
+ end
19
+
20
+ def self.configure
21
+ yield(config)
22
+ end
23
+
24
+ def self.git_command
25
+ "git '--git-dir=#{FightClub::WORKING_DIR}/#{FightClub.config.repo_name}/.git' '--work-tree=#{FightClub::WORKING_DIR}/#{FightClub.config.repo_name}'"
26
+ end
27
+ end
@@ -0,0 +1,49 @@
1
+ require 'git'
2
+ require 'logger'
3
+ require 'octokit'
4
+ require 'httparty'
5
+ require_relative 'config'
6
+ require_relative 'commenter'
7
+ require_relative 'repository'
8
+ require_relative 'merger'
9
+ require_relative 'rebaser'
10
+
11
+ module FightClub
12
+ class Arena
13
+ def initialize(base_pull, config = FightClub.config)
14
+ @base_pull = base_pull
15
+ end
16
+
17
+ def start
18
+ Repository.new.update(FightClub.config.uri, FightClub.config.repo_name)
19
+
20
+ git.checkout("origin/#{base_pull["head"]["ref"]}")
21
+
22
+ return unless base_pull["base"]["ref"] == FightClub.config.master_branch
23
+
24
+ return unless Rebaser.attempt_rebase(base_pull)
25
+
26
+ git.reset_hard("origin/#{base_pull["head"]["ref"]}")
27
+
28
+ pull_requests = client.pull_requests(FightClub.config.repo, :per_page => 200)
29
+
30
+ pull_requests.each do |pr|
31
+ Merger.new(base_pull, pr, git).execute
32
+ end
33
+
34
+ true
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :base_pull, :client, :git
40
+
41
+ def client
42
+ @client = Octokit::Client.new(access_token: FightClub.config.oauth)
43
+ end
44
+
45
+ def git
46
+ @git ||= Git.open("#{FightClub::WORKING_DIR}/#{FightClub.config.repo_name}", log: Logger.new(STDOUT))
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,19 @@
1
+ module FightClub
2
+ class Commenter
3
+ def self.comment(pr, message)
4
+ HTTParty.post(
5
+ pr["_links"]["comments"]["href"],
6
+ body: {
7
+ body: message,
8
+ }.to_json,
9
+ headers: {
10
+ 'Content-Type' => 'application/json',
11
+ 'User-Agent' => 'ruby',
12
+ "Authorization" => "token #{FightClub.config.oauth}"
13
+ }
14
+ )
15
+
16
+ Logger.new(STDOUT).info "Left a comment on #{pr["number"]} with message: #{message}"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module FightClub
2
+ class Config
3
+ attr_accessor :repo, :oauth, :repo_name, :uri, :master_branch
4
+
5
+ def initialize
6
+ @repo = 'baxterthehacker/public-repo'
7
+ @oauth = 'Not set'
8
+ @repo_name = 'public-repo'
9
+ @uri = 'git@github.com:baxterthehacker/public-repo.git'
10
+ @master_branch = 'master'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ module FightClub
2
+ class Merger
3
+ def initialize(base_pull, pr, git)
4
+ @base_pull = base_pull
5
+ @pr = pr
6
+ @git = git
7
+ end
8
+
9
+ def execute
10
+ Logger.new(STDOUT).info "Trying to merge #{pr.head.ref} into #{base_pull["head"]["ref"]}..."
11
+ return unless pr.base.ref == FightClub.config.master_branch
12
+ return if pr.head.ref == base_pull["head"]["ref"]
13
+
14
+ git.reset_hard("origin/#{base_pull["head"]["ref"]}")
15
+ git.checkout("origin/#{pr.head.ref}")
16
+ return unless Rebaser.attempt_rebase(pr)
17
+
18
+ git.checkout("origin/#{base_pull["head"]["ref"]}")
19
+
20
+ unless attempt_merge(pr)
21
+ Commenter.comment(pr, "Your branch currently conflicts with another open pull request: #{base_pull["_links"]["html"]["href"]}")
22
+ Commenter.comment(base_pull, "Your branch currently conflicts with another open pull request: #{pr._links.html.href}")
23
+ end
24
+ end
25
+
26
+ def attempt_merge(pr)
27
+ result = `#{FightClub.git_command} merge origin/#{pr.head.ref}`
28
+
29
+ !(result.include? 'CONFLICT')
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :base_pull, :pr, :git
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ module FightClub
2
+ class Rebaser
3
+ def self.attempt_rebase(pr)
4
+ result = `#{FightClub.git_command} rebase origin/#{FightClub.config.master_branch}`
5
+
6
+ if result.include? 'CONFLICT'
7
+ Commenter.comment(pr, 'Your branch is currently conflicting with the target branch. Please resolve all merge conflicts and repush.')
8
+ `#{FightClub.git_command} rebase --abort`
9
+
10
+ return false
11
+ end
12
+
13
+ true
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module FightClub
2
+ class Repository
3
+ WORKING_DIR = "#{Dir.pwd}/repos"
4
+
5
+ def update(uri, name)
6
+ system("mkdir #{WORKING_DIR}/#{name}") unless Dir.exists? "WORKING_DIR/#{name}"
7
+
8
+ git = Git.open("#{WORKING_DIR}/#{name}", :log => Logger.new(STDOUT))
9
+
10
+ unless File.exists?("#{WORKING_DIR}/#{name}/.gitconfig")
11
+ Logger.new(STDOUT).info "Cloning #{name}..."
12
+
13
+ git.clone(uri, name, :path => WORKING_DIR)
14
+ end
15
+
16
+ git.fetch
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module FightClub
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ [^.]*
2
+
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fight_club
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim Minkov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: git
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: octokit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - timothyminkov@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - fight-club.gemspec
96
+ - lib/fight_club.rb
97
+ - lib/fight_club/arena.rb
98
+ - lib/fight_club/commenter.rb
99
+ - lib/fight_club/config.rb
100
+ - lib/fight_club/merger.rb
101
+ - lib/fight_club/rebaser.rb
102
+ - lib/fight_club/repository.rb
103
+ - lib/fight_club/version.rb
104
+ - repos/.gitignore
105
+ homepage:
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.2.2
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Finds conflicts against open pull requests
129
+ test_files: []