git-pr-release 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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +28 -0
- data/README.md +35 -0
- data/bin/git-pr-release +168 -0
- data/git-pr-release.gemspec +24 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 98451853b6d661fc267e971bc26da386c77db073
|
4
|
+
data.tar.gz: 2437ff8212312fae03bbdfc28f2bae9e1b2806a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e03be692ee0bbb5a4ac1dd4cffd68fb625a39601cda7171d2c93770f4162b162e6cd5ae287877f4030ca2c4d65dafd442e8bd42803f0389c9f58178f5171aec5
|
7
|
+
data.tar.gz: d8831448a215b076fdd69782ccfdcbc5c22eeb979623f7cb0818754dbdc311fb07bb681eae75f0608af00dfdb89e592e8c0529746ecf3180dc5828966f8dcf3f
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
git-pr-release (0.0.1)
|
5
|
+
colorize (~> 0.6)
|
6
|
+
highline (~> 1.6)
|
7
|
+
octokit (~> 2.7)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.3.5)
|
13
|
+
colorize (0.6.0)
|
14
|
+
faraday (0.9.0)
|
15
|
+
multipart-post (>= 1.2, < 3)
|
16
|
+
highline (1.6.20)
|
17
|
+
multipart-post (2.0.0)
|
18
|
+
octokit (2.7.0)
|
19
|
+
sawyer (~> 0.5.2)
|
20
|
+
sawyer (0.5.2)
|
21
|
+
addressable (~> 2.3.5)
|
22
|
+
faraday (~> 0.8, < 0.10)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
git-pr-release!
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
git-pr-release
|
2
|
+
==============
|
3
|
+
|
4
|
+
Creates a pull request which summarizes feature branches that are to be
|
5
|
+
released into production. Useful if your branching storategy is like below:
|
6
|
+
|
7
|
+
* Feature branches are first merged into "staging" (or release, development)
|
8
|
+
branch.
|
9
|
+
* Then the staging branch is merged into "production" branch, which is for
|
10
|
+
production release.
|
11
|
+
|
12
|
+
Configuration
|
13
|
+
-------------
|
14
|
+
|
15
|
+
All configuration are taken using `git config`.
|
16
|
+
|
17
|
+
### `pr-release.token`
|
18
|
+
|
19
|
+
Token for GitHub API.
|
20
|
+
|
21
|
+
If not set, you will be asked to input username/password for one time only,
|
22
|
+
and this configuration variable will be stored.
|
23
|
+
|
24
|
+
### `pr-release.branch.production`
|
25
|
+
|
26
|
+
The branch name that is deployed in production environment.
|
27
|
+
|
28
|
+
Default value: `master`.
|
29
|
+
|
30
|
+
### `pr-release.branch.staging`
|
31
|
+
|
32
|
+
The branch name that the feature branches are merged into and is going to be
|
33
|
+
merged into the "production" branch.
|
34
|
+
|
35
|
+
Default value: `staging`.
|
data/bin/git-pr-release
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'uri'
|
5
|
+
require 'open3'
|
6
|
+
require 'octokit'
|
7
|
+
require 'colorize'
|
8
|
+
|
9
|
+
def say(message, level)
|
10
|
+
color = case level
|
11
|
+
when :trace
|
12
|
+
return unless ENV['DEBUG']
|
13
|
+
nil
|
14
|
+
when :debug
|
15
|
+
return unless ENV['DEBUG']
|
16
|
+
:blue
|
17
|
+
when :info
|
18
|
+
:green
|
19
|
+
when :notice
|
20
|
+
:yellow
|
21
|
+
when :warn
|
22
|
+
:magenta
|
23
|
+
when :error
|
24
|
+
:red
|
25
|
+
end
|
26
|
+
|
27
|
+
puts message.colorize(color)
|
28
|
+
end
|
29
|
+
|
30
|
+
def git(*command)
|
31
|
+
command = [ 'git', *command.map(&:to_s) ]
|
32
|
+
say "Executing `#{command.join(' ')}`", :trace
|
33
|
+
out, status = Open3.capture2(*command)
|
34
|
+
unless status.success?
|
35
|
+
raise "Executing `#{command.join(' ')}` failed: #{status}"
|
36
|
+
end
|
37
|
+
out.each_line
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def git_config(key)
|
42
|
+
begin
|
43
|
+
git('config', key).first.chomp
|
44
|
+
rescue
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_description(pull_requests)
|
50
|
+
pull_requests.map do |pr|
|
51
|
+
"- [ ] ##{pr.number} #{pr.title}" + (pr.assignee ? " @#{pr.assignee.login}" : '')
|
52
|
+
end.join("\n")
|
53
|
+
end
|
54
|
+
|
55
|
+
def obtain_token!
|
56
|
+
token = git_config('pr-release.token')
|
57
|
+
|
58
|
+
unless token
|
59
|
+
require 'highline/import'
|
60
|
+
STDERR.puts 'Could not obtain config variable pr-release.token.'
|
61
|
+
STDERR.puts 'Trying to generate token...'
|
62
|
+
|
63
|
+
username = ask('username? ') { |q| q.default = ENV['USER'] }
|
64
|
+
password = ask('password? (not saved) ') { |q| q.echo = '*' }
|
65
|
+
|
66
|
+
temporary_client = Octokit::Client.new :login => username, :password => password
|
67
|
+
|
68
|
+
auth = temporary_client.create_authorization({ :scopes => [ 'public_repo', 'repo' ], :note => 'summerize-release' })
|
69
|
+
token = auth.token
|
70
|
+
git :config, '--global', 'pr-release.token', token
|
71
|
+
end
|
72
|
+
|
73
|
+
token
|
74
|
+
end
|
75
|
+
|
76
|
+
remote = git_config 'remote.origin.url'
|
77
|
+
unless %r(^\w+://) === remote
|
78
|
+
remote = "ssh://#{remote.sub(':', '/')}"
|
79
|
+
end
|
80
|
+
|
81
|
+
remote_url = URI.parse(remote)
|
82
|
+
repository = remote_url.path.sub(%r(^/), '').sub(/\.git$/, '')
|
83
|
+
|
84
|
+
if remote_url.host != 'github.com'
|
85
|
+
# GitHub:Enterprise
|
86
|
+
OpenSSL::SSL.const_set :VERIFY_PEER, OpenSSL::SSL::VERIFY_NONE # XXX
|
87
|
+
|
88
|
+
Octokit.configure do |c|
|
89
|
+
c.api_endpoint = "https://#{remote_url.host}/api/v3"
|
90
|
+
c.web_endpoint = "https://#{remote_url.host}/"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
## Project specific configuration
|
95
|
+
production_branch = git_config('pr-release.branch.production') || 'master'
|
96
|
+
staging_branch = git_config('pr-release.branch.staging') || 'staging'
|
97
|
+
|
98
|
+
say "Repository: #{repository}", :debug
|
99
|
+
say "Production branch: #{production_branch}", :debug
|
100
|
+
say "Staging branch: #{staging_branch}", :debug
|
101
|
+
|
102
|
+
client = Octokit::Client.new :access_token => obtain_token!
|
103
|
+
|
104
|
+
git :remote, 'update', 'origin'
|
105
|
+
|
106
|
+
merged_feature_head_sha1s = git(
|
107
|
+
:log, '--merges', '--pretty=format:%P', "origin/#{production_branch}..origin/#{staging_branch}"
|
108
|
+
).map do |line|
|
109
|
+
main_sha1, feature_sha1 = line.chomp.split /\s+/
|
110
|
+
feature_sha1
|
111
|
+
end
|
112
|
+
|
113
|
+
merged_pull_request_numbers = git('ls-remote', 'origin', 'refs/pull/*/head').map do |line|
|
114
|
+
sha1, ref = line.chomp.split /\s+/
|
115
|
+
|
116
|
+
if merged_feature_head_sha1s.include? sha1
|
117
|
+
if %r<^refs/pull/(\d+)/head$>.match ref
|
118
|
+
pr_number = $1.to_i
|
119
|
+
|
120
|
+
if git('merge-base', sha1, "origin/#{production_branch}").first.chomp == sha1
|
121
|
+
say "##{pr_number} (#{sha1}) is already merged into #{production_branch}", :debug
|
122
|
+
else
|
123
|
+
pr_number
|
124
|
+
end
|
125
|
+
else
|
126
|
+
say "Bad pull request head ref format: #{ref}", :warn
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end.compact
|
131
|
+
|
132
|
+
if merged_pull_request_numbers.empty?
|
133
|
+
say 'No pull requests to be released', :error
|
134
|
+
exit 1
|
135
|
+
end
|
136
|
+
|
137
|
+
pull_requests = merged_pull_request_numbers.map do |nr|
|
138
|
+
pr = client.pull_request repository, nr
|
139
|
+
say "To be released: ##{pr.number} #{pr.title}", :notice
|
140
|
+
pr
|
141
|
+
end
|
142
|
+
|
143
|
+
say 'Searching for existing release pull requests...', :info
|
144
|
+
release_pr = client.pull_requests(repository).find do |pr|
|
145
|
+
pr.head.ref == staging_branch && pr.base.ref == production_branch
|
146
|
+
end
|
147
|
+
|
148
|
+
created = false
|
149
|
+
|
150
|
+
if release_pr
|
151
|
+
say "Updating release pull request ##{release_pr.number}...", :info
|
152
|
+
client.update_pull_request(
|
153
|
+
repository, release_pr.number, :body => generate_description(pull_requests)
|
154
|
+
)
|
155
|
+
else
|
156
|
+
say 'Creating release pull request...', :info
|
157
|
+
release_pr = client.create_pull_request(
|
158
|
+
repository, production_branch, staging_branch, "release #{Time.now}", generate_description(pull_requests)
|
159
|
+
)
|
160
|
+
created = true
|
161
|
+
end
|
162
|
+
|
163
|
+
unless release_pr
|
164
|
+
say 'No pull request found/created', :error
|
165
|
+
exit 1
|
166
|
+
end
|
167
|
+
|
168
|
+
say "#{created ? 'Created' : 'Updated'} pull request: #{release_pr.rels[:html].href}", :notice
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "git-pr-release"
|
7
|
+
spec.version = '0.0.1'
|
8
|
+
spec.authors = ["motemen"]
|
9
|
+
spec.email = ["motemen@gmail.com"]
|
10
|
+
spec.summary = 'Creates a release pull request'
|
11
|
+
spec.description = 'git-pr-release creates a pull request which summarizes feature branches that are to be released into production'
|
12
|
+
spec.homepage = 'https://github.com/motemen/git-pr-release'
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($/)
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_dependency 'octokit', '~> 2.7'
|
20
|
+
spec.add_dependency 'highline', '~> 1.6'
|
21
|
+
spec.add_dependency 'colorize', '~> 0.6'
|
22
|
+
|
23
|
+
spec.license = 'MIT'
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-pr-release
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- motemen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: highline
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.6'
|
55
|
+
description: git-pr-release creates a pull request which summarizes feature branches
|
56
|
+
that are to be released into production
|
57
|
+
email:
|
58
|
+
- motemen@gmail.com
|
59
|
+
executables:
|
60
|
+
- git-pr-release
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- Gemfile
|
66
|
+
- Gemfile.lock
|
67
|
+
- README.md
|
68
|
+
- bin/git-pr-release
|
69
|
+
- git-pr-release.gemspec
|
70
|
+
homepage: https://github.com/motemen/git-pr-release
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.0.3
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Creates a release pull request
|
94
|
+
test_files: []
|
95
|
+
has_rdoc:
|