github_pulley 0.1.0
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/.gitignore +4 -0
- data/Gemfile +6 -0
- data/README.markdown +32 -0
- data/Rakefile +1 -0
- data/bin/pulley +37 -0
- data/github_pulley.gemspec +22 -0
- data/lib/github_pulley/base.rb +118 -0
- data/lib/github_pulley/exception.rb +3 -0
- data/lib/github_pulley/version.rb +3 -0
- data/lib/github_pulley.rb +24 -0
- metadata +106 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# GithubPulley
|
2
|
+
### A ruby gem for creating github pull requests
|
3
|
+
|
4
|
+
This gem serves no other purpose but to allow github users
|
5
|
+
to quickly attach a branch to an issue via a pull request.
|
6
|
+
A feature which is currently only available via the API.
|
7
|
+
|
8
|
+
### Why
|
9
|
+
|
10
|
+
Our goal is to use GitHub issues for code reviews and tracking stories. In other words
|
11
|
+
we want to eschew using Pivotal Tracker until we're big enough to care.
|
12
|
+
|
13
|
+
### Install
|
14
|
+
|
15
|
+
gem install github-pulley
|
16
|
+
|
17
|
+
### Use
|
18
|
+
|
19
|
+
cd /myproject
|
20
|
+
git co -b some_new_feature
|
21
|
+
# Add the feature
|
22
|
+
git ci -am "Added the ability to send emails"
|
23
|
+
pulley attach 4 # push and attach this branch to issue #4
|
24
|
+
|
25
|
+
Later someone can review the pull request, and merge the code(which also closes
|
26
|
+
the issue)
|
27
|
+
|
28
|
+
### Respecting Forking
|
29
|
+
|
30
|
+
This gem respects the github forking process. It assumes that if you fork
|
31
|
+
a repository, the remote will be named 'upstream', and pull requests
|
32
|
+
will be sent to the upstream repository if it exists.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/pulley
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
+
require 'github_pulley'
|
4
|
+
|
5
|
+
class Runner < Optitron::CLI
|
6
|
+
|
7
|
+
def pulley
|
8
|
+
@pulley ||= GithubPulley.new
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Attach a branch to an issue with a pull request"
|
12
|
+
arg_types :numeric
|
13
|
+
def attach(issue)
|
14
|
+
pulley.attach_pull_request_to_issue(issue)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Create a pull request for the current branch"
|
18
|
+
arg_types :string
|
19
|
+
opt 'body', :type => :string
|
20
|
+
def create(title)
|
21
|
+
pulley.create_pull_request(title, params['body'])
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Get a list of my open issues"
|
25
|
+
def open
|
26
|
+
pulley.get_open_issues
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
Runner.dispatch
|
33
|
+
rescue GithubPulley::Error => e
|
34
|
+
puts e.message
|
35
|
+
rescue Octokit::Error => e
|
36
|
+
puts e.message
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "github_pulley/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "github_pulley"
|
7
|
+
s.version = GithubPulley::VERSION
|
8
|
+
s.authors = ["Mark Percival"]
|
9
|
+
s.email = ["m@mdp.im"]
|
10
|
+
s.homepage = "https://github.com/mdp/pulley"
|
11
|
+
s.summary = "Work with Github Issues and Pull Requests"
|
12
|
+
s.description = %q{We're small and trying to eschew the use of a bigger project tracker}
|
13
|
+
|
14
|
+
s.rubyforge_project = "pulley"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.add_runtime_dependency 'json'
|
21
|
+
s.add_runtime_dependency 'octokit', "= 0.6.4"
|
22
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module GithubPulley
|
2
|
+
class Base
|
3
|
+
def initialize
|
4
|
+
@octokit = Octokit::Client.new(:login => github_user, :token => github_token)
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_open_issues(opts={})
|
8
|
+
# Listing by assignee seems to be broken
|
9
|
+
all_open_issues.each do |issue|
|
10
|
+
print_issue(issue)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def attach_pull_request_to_issue(issue, opts={})
|
15
|
+
opts = {
|
16
|
+
:base => 'master',
|
17
|
+
:head => "#{upstream_user||origin_user}:#{current_branch}",
|
18
|
+
:branch => current_branch
|
19
|
+
}.merge(opts)
|
20
|
+
puts "Pushing to #{opts[:branch]} on 'origin'"
|
21
|
+
`git push origin #{opts[:branch]}`
|
22
|
+
pull_to = forked_from || origin_repo
|
23
|
+
# @octokit.create_pull_request_for_issue(repo, base, head, issue, options={})
|
24
|
+
# Returns nil if successfull
|
25
|
+
@octokit.create_pull_request_for_issue(pull_to, opts[:base], opts[:head], issue)
|
26
|
+
|
27
|
+
issue_details = @octokit.issue(repo, issue)
|
28
|
+
print_issue(issue_details, "Attached to")
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_pull_request(title, body='', opts={})
|
32
|
+
opts = {
|
33
|
+
:base => 'master',
|
34
|
+
:head => "#{upstream_user||origin_user}:#{current_branch}",
|
35
|
+
:branch => current_branch
|
36
|
+
}.merge(opts)
|
37
|
+
puts "Pushing to #{opts[:branch]} on 'origin'"
|
38
|
+
`git push origin #{opts[:branch]}`
|
39
|
+
pull_to = forked_from || origin_repo
|
40
|
+
@octokit.create_pull_request(pull_to, opts[:base], opts[:head], title, body)
|
41
|
+
# Returns nil if successfull
|
42
|
+
puts "Created new pull request"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def all_open_issues
|
48
|
+
@octokit.get("/api/v2/json/issues/list/#{Octokit::Repository.new(repo)}/open")['issues']
|
49
|
+
end
|
50
|
+
|
51
|
+
def github_user
|
52
|
+
@github_user ||= `git config github.user`.strip
|
53
|
+
raise Error, "Please set github.user" if @github_user.empty?
|
54
|
+
@github_user
|
55
|
+
end
|
56
|
+
|
57
|
+
def github_token
|
58
|
+
@github_token ||= `git config github.token`.strip
|
59
|
+
raise Error, "Please set github.token" if @github_token.empty?
|
60
|
+
@github_token
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_branch
|
64
|
+
`git name-rev HEAD 2> /dev/null | awk "{ print \\$2 }"`.strip
|
65
|
+
end
|
66
|
+
|
67
|
+
def forked_from
|
68
|
+
@octokit.repository(origin_repo)['source']
|
69
|
+
end
|
70
|
+
|
71
|
+
def repo
|
72
|
+
@repo ||= upstream_repo || origin_repo
|
73
|
+
end
|
74
|
+
|
75
|
+
def upstream_repo
|
76
|
+
unless @upstream_repo
|
77
|
+
if r = git('config remote.upstream.url')
|
78
|
+
@upstream_repo = r[/\:(.+)\.git$/, 1]
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
@upstream_repo
|
84
|
+
end
|
85
|
+
|
86
|
+
def origin_repo
|
87
|
+
unless @origin_repo
|
88
|
+
unless r = git('config remote.origin.url')
|
89
|
+
raise Error, "Can't find remote 'origin'"
|
90
|
+
end
|
91
|
+
@origin_repo = r[/\:(.+)\.git$/, 1]
|
92
|
+
end
|
93
|
+
@origin_repo
|
94
|
+
end
|
95
|
+
|
96
|
+
def origin_user
|
97
|
+
origin_repo[/(.+)\/.+/, 1]
|
98
|
+
end
|
99
|
+
|
100
|
+
def upstream_user
|
101
|
+
upstream_repo[/(.+)\/.+/, 1] if upstream_repo
|
102
|
+
end
|
103
|
+
|
104
|
+
def print_issue(issue, prefix_msg)
|
105
|
+
puts "#{prefix_msg}: ##{issue.number} - #{issue.title}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def git(cmd)
|
109
|
+
result = `git #{cmd}`.strip
|
110
|
+
if result.length == 0
|
111
|
+
false
|
112
|
+
else
|
113
|
+
result
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "optitron"
|
2
|
+
require "octokit"
|
3
|
+
require "github_pulley/base"
|
4
|
+
require "github_pulley/version"
|
5
|
+
require "github_pulley/exception"
|
6
|
+
|
7
|
+
module GithubPulley
|
8
|
+
class << self
|
9
|
+
# Alias for GithubPulley::Base.new
|
10
|
+
def new
|
11
|
+
GithubPulley::Base.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method, *args, &block)
|
15
|
+
return super unless new.respond_to?(method)
|
16
|
+
new.send(method, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to?(method, include_private=false)
|
20
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: github_pulley
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mark Percival
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-02 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: json
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: octokit
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 15
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 6
|
47
|
+
- 4
|
48
|
+
version: 0.6.4
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
description: We're small and trying to eschew the use of a bigger project tracker
|
52
|
+
email:
|
53
|
+
- m@mdp.im
|
54
|
+
executables:
|
55
|
+
- pulley
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- .gitignore
|
62
|
+
- Gemfile
|
63
|
+
- README.markdown
|
64
|
+
- Rakefile
|
65
|
+
- bin/pulley
|
66
|
+
- github_pulley.gemspec
|
67
|
+
- lib/github_pulley.rb
|
68
|
+
- lib/github_pulley/base.rb
|
69
|
+
- lib/github_pulley/exception.rb
|
70
|
+
- lib/github_pulley/version.rb
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: https://github.com/mdp/pulley
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project: pulley
|
101
|
+
rubygems_version: 1.6.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Work with Github Issues and Pull Requests
|
105
|
+
test_files: []
|
106
|
+
|