github_workflow 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/README.md +15 -0
- data/Rakefile +2 -0
- data/bin/github_workflow +5 -0
- data/github_workflow.gemspec +26 -0
- data/lib/github_workflow/cli.rb +240 -0
- data/lib/github_workflow/version.rb +3 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c9d551fbda6a545a0fb85ffbcefeb43a8bfb1f9c
|
4
|
+
data.tar.gz: 9c6895664cdd69ce38ee216cef9422b3e4cf3493
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3aa3959df85a40b3334a23353779bd79dde7f108eaf2d0f5313668096410e4d5012ec371aa80a88cad9ebb4195ee1cdf31c80b10b06539e294f80f5685ab94fa
|
7
|
+
data.tar.gz: 68f184bb3c52de1769f8d83a5e4e564e2f57dbbdc6607439c177e78ec1d4ec4a3bb5cdea2faf1045b0578cce611a51530ffb47daa6bf2d980d04ee0916bafaf5
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Github Workflow
|
2
|
+
|
3
|
+
```
|
4
|
+
$ bin/github_workflow -h
|
5
|
+
|
6
|
+
Commands:
|
7
|
+
github_workflow create_and_start -m, --name=NAME # Create and start issue
|
8
|
+
github_workflow create_pr # Convert Issue to Pull Request
|
9
|
+
github_workflow help [COMMAND] # Describe available commands or one specific command
|
10
|
+
github_workflow info # Print out issue description
|
11
|
+
github_workflow open # Open issue or PR in browser
|
12
|
+
github_workflow push_and_pr # Push branch to origin and convert Issue to Pull Request
|
13
|
+
github_workflow start -i, --issue-id=ISSUE_ID # Create branch named with issue number and issue title
|
14
|
+
github_workflow status # Check PR CI status
|
15
|
+
```
|
data/Rakefile
ADDED
data/bin/github_workflow
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "github_workflow/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "github_workflow"
|
8
|
+
spec.version = GithubWorkflow::VERSION
|
9
|
+
spec.authors = ["Ben Liscio"]
|
10
|
+
spec.email = ["bliscio@daisybill.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{DaisyBill's internal github workflows}
|
13
|
+
spec.homepage = "https://github.com/daisybill/github_workflow"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "thor", "~> 0.19"
|
21
|
+
spec.add_dependency "faraday", "~> 0.11"
|
22
|
+
spec.add_dependency "terminal-table", "~> 1.5"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "faraday"
|
3
|
+
require "thor"
|
4
|
+
require "open3"
|
5
|
+
require "json"
|
6
|
+
require "terminal-table"
|
7
|
+
|
8
|
+
module GithubWorkflow
|
9
|
+
class Cli < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
default_task :start
|
13
|
+
|
14
|
+
desc "start", "Create branch named with issue number and issue title"
|
15
|
+
method_option :issue_id, aliases: "-i", type: :string, required: true
|
16
|
+
|
17
|
+
def start
|
18
|
+
ensure_github_config_present
|
19
|
+
checkout_master
|
20
|
+
rebase_master
|
21
|
+
create_branch
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "create_pr", "Convert Issue to Pull Request"
|
25
|
+
|
26
|
+
def create_pr
|
27
|
+
ensure_github_config_present
|
28
|
+
ensure_origin_exists
|
29
|
+
convert_issue_to_pr
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "push_and_pr", "Push branch to origin and convert Issue to Pull Request"
|
33
|
+
|
34
|
+
def push_and_pr
|
35
|
+
ensure_github_config_present
|
36
|
+
push_and_set_upstream
|
37
|
+
convert_issue_to_pr
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "status", "Check PR CI status"
|
41
|
+
|
42
|
+
def status
|
43
|
+
ensure_github_config_present
|
44
|
+
ensure_origin_exists
|
45
|
+
response = JSON.parse(github_client.get("repos/#{user_and_repo}/statuses/#{current_branch}?access_token=#{oauth_token}").body)
|
46
|
+
|
47
|
+
if response.empty?
|
48
|
+
alert "No statuses yet. Have you pushed your branch?"
|
49
|
+
else
|
50
|
+
table = Terminal::Table.new(style: { width: 80 }) do |table_rows|
|
51
|
+
table_rows << %w(CI Status Description)
|
52
|
+
table_rows << :separator
|
53
|
+
|
54
|
+
response.map { |status| status["context"] }.uniq.map do |status|
|
55
|
+
response.select { |st| st["context"] == status }.sort_by { |st| st["updated_at"] }.last
|
56
|
+
end.each do |status|
|
57
|
+
table_rows << %w(context state description).map { |key| status[key] }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
puts table
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "info", "Print out issue description"
|
66
|
+
|
67
|
+
def info
|
68
|
+
ensure_github_config_present
|
69
|
+
response = JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{issue_number_from_branch}?access_token=#{oauth_token}").body)
|
70
|
+
puts response["body"]
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "open", "Open issue or PR in browser"
|
74
|
+
|
75
|
+
def open
|
76
|
+
ensure_github_config_present
|
77
|
+
response = JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{issue_number_from_branch}?access_token=#{oauth_token}").body)
|
78
|
+
`/usr/bin/open -a "/Applications/Google Chrome.app" '#{response["html_url"]}'`
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "create_and_start", "Create and start issue"
|
82
|
+
|
83
|
+
method_option :name, aliases: "-m", type: :string, required: true
|
84
|
+
|
85
|
+
def create_and_start
|
86
|
+
ensure_github_config_present
|
87
|
+
create_issue
|
88
|
+
end
|
89
|
+
|
90
|
+
no_tasks do
|
91
|
+
def create_branch
|
92
|
+
`git checkout -b #{branch_name_for_issue_number}`
|
93
|
+
end
|
94
|
+
|
95
|
+
def ensure_origin_exists
|
96
|
+
Open3.capture2("git rev-parse --abbrev-ref --symbolic-full-name @{u}").tap do |_, status|
|
97
|
+
unless status.success?
|
98
|
+
failure("Upstream branch does not exist. Please set before creating pull request. E.g., `git push -u origin branch_name`")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def ensure_github_config_present
|
104
|
+
unless project_config && project_config["oauth_token"] && project_config["user_and_repo"]
|
105
|
+
failure('Please add `.github` file containing `{ "oauth": "TOKEN", "repo": "user/repo" }`')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def project_config
|
110
|
+
@project_config ||= JSON.parse(File.read(".github")) rescue nil
|
111
|
+
end
|
112
|
+
|
113
|
+
def oauth_token
|
114
|
+
project_config["oauth_token"]
|
115
|
+
end
|
116
|
+
|
117
|
+
def user_and_repo
|
118
|
+
project_config["user_and_repo"]
|
119
|
+
end
|
120
|
+
|
121
|
+
def push_and_set_upstream
|
122
|
+
`git rev-parse --abbrev-ref HEAD | XARGS git push origin -u`
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_issue
|
126
|
+
github_client.post(
|
127
|
+
"repos/#{user_and_repo}/issues?access_token=#{oauth_token}",
|
128
|
+
JSON.generate(
|
129
|
+
{
|
130
|
+
title: options[:name]
|
131
|
+
}
|
132
|
+
)
|
133
|
+
).tap do |response|
|
134
|
+
if response.success?
|
135
|
+
pass("Issue created")
|
136
|
+
@issue_id = JSON.parse(response.body)["number"]
|
137
|
+
start
|
138
|
+
else
|
139
|
+
alert("An error occurred when creating issue:")
|
140
|
+
alert("#{response.status}: #{JSON.parse(response.body)['message']}")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def issue_id
|
146
|
+
@issue_id ||= options[:issue_id]
|
147
|
+
end
|
148
|
+
|
149
|
+
def convert_issue_to_pr
|
150
|
+
github_client.post(
|
151
|
+
"repos/#{user_and_repo}/pulls?access_token=#{oauth_token}",
|
152
|
+
JSON.generate(
|
153
|
+
{
|
154
|
+
head: current_branch,
|
155
|
+
base: "master",
|
156
|
+
issue: issue_number_from_branch
|
157
|
+
}
|
158
|
+
)
|
159
|
+
).tap do |response|
|
160
|
+
if response.success?
|
161
|
+
pass("Issue converted to Pull Request")
|
162
|
+
say_info(JSON.parse(response.body)["url"])
|
163
|
+
else
|
164
|
+
alert("An error occurred when creating PR:")
|
165
|
+
alert("#{response.status}: #{JSON.parse(response.body)['message']}")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def issue_number_from_branch
|
171
|
+
current_branch.split("_").first.tap do |issue_number|
|
172
|
+
if !issue_number
|
173
|
+
failure("Unable to parse issue number from branch. Are you sure you have a branch checked out?")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def current_branch
|
179
|
+
`git rev-parse --abbrev-ref HEAD`.chomp
|
180
|
+
end
|
181
|
+
|
182
|
+
def branch_name_for_issue_number
|
183
|
+
issue = JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{issue_id}?access_token=#{oauth_token}").body)
|
184
|
+
"#{issue['number']}_#{issue['title'].strip.downcase.gsub(/[^a-zA-Z0-9]/, '_').squeeze("_")}"
|
185
|
+
end
|
186
|
+
|
187
|
+
def github_client
|
188
|
+
Faraday.new(url: "https://api.github.com") do |faraday|
|
189
|
+
faraday.request :url_encoded
|
190
|
+
faraday.adapter Faraday.default_adapter
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def rebase_master
|
195
|
+
say_info("Fetching changes and rebaseing master")
|
196
|
+
|
197
|
+
if success?("git pull --rebase")
|
198
|
+
pass("Fetched and rebased")
|
199
|
+
else
|
200
|
+
failure("Failed to fetch or rebase")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def checkout_master
|
205
|
+
say_info("Checking out master")
|
206
|
+
|
207
|
+
if success?("git checkout master")
|
208
|
+
pass("Checked out master")
|
209
|
+
else
|
210
|
+
failure("Failed to checkout master")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def success?(command)
|
215
|
+
IO.popen(command) do |output|
|
216
|
+
output.each { |line| puts line }
|
217
|
+
end
|
218
|
+
|
219
|
+
$?.success?
|
220
|
+
end
|
221
|
+
|
222
|
+
def alert(message)
|
223
|
+
say_status("ALERT", message, :red)
|
224
|
+
end
|
225
|
+
|
226
|
+
def say_info(message)
|
227
|
+
say_status("INFO", message, :black)
|
228
|
+
end
|
229
|
+
|
230
|
+
def pass(message)
|
231
|
+
say_status("OK", message, :green)
|
232
|
+
end
|
233
|
+
|
234
|
+
def failure(message)
|
235
|
+
say_status("FAIL", message, :red)
|
236
|
+
exit
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: github_workflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Liscio
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.19'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.19'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.11'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: terminal-table
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.14'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- bliscio@daisybill.com
|
86
|
+
executables:
|
87
|
+
- github_workflow
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".ruby-version"
|
93
|
+
- Gemfile
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- bin/github_workflow
|
97
|
+
- github_workflow.gemspec
|
98
|
+
- lib/github_workflow/cli.rb
|
99
|
+
- lib/github_workflow/version.rb
|
100
|
+
homepage: https://github.com/daisybill/github_workflow
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.5.1
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: DaisyBill's internal github workflows
|
124
|
+
test_files: []
|