github_workflow 0.4.0 → 0.4.3
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 +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/README.md +29 -13
- data/lib/github_workflow/cli.rb +76 -20
- data/lib/github_workflow/daisybill.rb +34 -0
- data/lib/github_workflow/gh_cli_client.rb +33 -14
- data/lib/github_workflow/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 221999fe5304093bf6533718d5866ad58dc006af43945177f65e65d058dc6c8c
|
4
|
+
data.tar.gz: f48cea6b9a3a7588cc47f70ff257e54c4316edda6394df12cb3c25dfedb2f6de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 238cf09eaabe2ed9d28cd57d187f88a470a1e4614e188eb6ee709b16521848be294944c12f1571961baef940f3929e9a13bdeea0ee46c4ebff0cdd36ce4b3646
|
7
|
+
data.tar.gz: ea20ea5e64ff0432454c18d206bcffa3b448dd32c56e708e979de4a090875099c6737059fd9a5b8e1ad9a87482dc88a53786f2b4c76b6f593a16a54d834bb31a
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.1.3
|
data/README.md
CHANGED
@@ -1,26 +1,42 @@
|
|
1
1
|
# Setup
|
2
2
|
|
3
|
-
|
3
|
+
## GitHub CLI
|
4
4
|
|
5
|
+
Install instructions:
|
6
|
+
|
7
|
+
### MacOS:
|
5
8
|
`brew install gh`
|
6
9
|
|
7
|
-
|
10
|
+
### Ubuntu
|
11
|
+
|
12
|
+
1. Add a reference to the package repository
|
13
|
+
* `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key C99B11DEB97541F0`
|
14
|
+
* `sudo apt-add-repository https://cli.github.com/packages`
|
15
|
+
2. Install the Github CLI
|
16
|
+
* `sudo apt update`
|
17
|
+
* `sudo apt install gh`
|
18
|
+
|
19
|
+
## Heroku CLI
|
8
20
|
|
9
|
-
|
21
|
+
For some commands you may need the [heroku cli installed](https://devcenter.heroku.com/articles/heroku-cli#install-the-heroku-cli)
|
10
22
|
|
11
|
-
#
|
23
|
+
# Commands
|
12
24
|
|
13
25
|
```
|
14
26
|
$ bin/github_workflow -h
|
15
27
|
|
16
28
|
Commands:
|
17
|
-
github_workflow
|
18
|
-
github_workflow
|
19
|
-
github_workflow
|
20
|
-
github_workflow
|
21
|
-
github_workflow
|
22
|
-
github_workflow
|
23
|
-
github_workflow
|
24
|
-
github_workflow
|
25
|
-
github_workflow
|
29
|
+
github_workflow cleanup # Remove merged PR branches
|
30
|
+
github_workflow create_and_start -m, --name=NAME # Create and start issue
|
31
|
+
github_workflow create_pr # Convert Issue to Pull Request
|
32
|
+
github_workflow deploy_diff # view deployment diff between staging and production for apps
|
33
|
+
github_workflow deploy_notes -r, --commit-range=COMMIT_RANGE # Generate Deploy notes for a range of commits
|
34
|
+
github_workflow help [COMMAND] # Describe available commands or one specific command
|
35
|
+
github_workflow info # Print out issue description
|
36
|
+
github_workflow issues # Show issue information for the organization
|
37
|
+
github_workflow open # Open issue or PR in browser
|
38
|
+
github_workflow push_and_pr # Push branch to origin and convert Issue to Pull Request
|
39
|
+
github_workflow reviews # Displays count of requested reviews for each user
|
40
|
+
github_workflow start -i, --issue-id=ISSUE_ID # Create branch named with issue number and issue title
|
41
|
+
github_workflow status # Check PR CI status
|
26
42
|
```
|
data/lib/github_workflow/cli.rb
CHANGED
@@ -5,10 +5,12 @@ require "open3"
|
|
5
5
|
require "json"
|
6
6
|
require "terminal-table"
|
7
7
|
require_relative "gh_cli_client.rb"
|
8
|
+
require_relative "daisybill.rb"
|
8
9
|
|
9
10
|
module GithubWorkflow
|
10
11
|
class Cli < Thor
|
11
12
|
PROCEED_TEXT = "Proceed? [y,yes]: ".freeze
|
13
|
+
TRUNCATE_DEFAULT = 50
|
12
14
|
|
13
15
|
include Thor::Actions
|
14
16
|
|
@@ -16,15 +18,18 @@ module GithubWorkflow
|
|
16
18
|
|
17
19
|
desc "start", "Create branch named with issue number and issue title"
|
18
20
|
method_option :issue_id, aliases: "-i", type: :string, required: true
|
21
|
+
method_option :truncate_branch_at, aliases: "-t", type: :numeric, default: TRUNCATE_DEFAULT
|
22
|
+
method_option :no_checkout, type: :boolean, required: false, default: false
|
19
23
|
def start
|
20
24
|
stash
|
21
25
|
rebase_main
|
22
|
-
create_branch
|
26
|
+
create_branch(options[:no_checkout])
|
23
27
|
stash_pop
|
24
28
|
end
|
25
29
|
|
26
30
|
desc "create_pr", "Convert Issue to Pull Request"
|
27
31
|
method_option :base_branch, aliases: "-b", type: :string
|
32
|
+
method_option :draft, aliases: "-d", type: :boolean, required: false, default: true
|
28
33
|
def create_pr
|
29
34
|
ensure_origin_exists
|
30
35
|
convert_issue_to_pr
|
@@ -32,6 +37,7 @@ module GithubWorkflow
|
|
32
37
|
|
33
38
|
desc "push_and_pr", "Push branch to origin and convert Issue to Pull Request"
|
34
39
|
method_option :base_branch, aliases: "-b", type: :string
|
40
|
+
method_option :draft, aliases: "-d", type: :boolean, required: false, default: true
|
35
41
|
def push_and_pr
|
36
42
|
push_and_set_upstream
|
37
43
|
convert_issue_to_pr
|
@@ -75,6 +81,8 @@ module GithubWorkflow
|
|
75
81
|
|
76
82
|
desc "create_and_start", "Create and start issue"
|
77
83
|
method_option :name, aliases: "-m", type: :string, required: true
|
84
|
+
method_option :truncate_branch_at, aliases: "-t", type: :numeric, default: TRUNCATE_DEFAULT
|
85
|
+
method_option :no_checkout, type: :boolean, required: false, default: false
|
78
86
|
def create_and_start
|
79
87
|
create_issue
|
80
88
|
end
|
@@ -118,10 +126,44 @@ module GithubWorkflow
|
|
118
126
|
end
|
119
127
|
end
|
120
128
|
|
129
|
+
desc "deploy_diff", "view deployment diff between staging and production for apps"
|
130
|
+
method_option :all, aliases: "-a", type: :boolean, default: false
|
131
|
+
def deploy_diff
|
132
|
+
apps = Daisybill::APPS
|
133
|
+
unless options[:all]
|
134
|
+
current_repo = github_client.get_repo_info
|
135
|
+
apps.reject! do |a|
|
136
|
+
a[:github_org] != current_repo[:owner] || a[:github_repo] != current_repo[:repo]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
apps.each do |app|
|
141
|
+
owner = app[:github_org]
|
142
|
+
repo = app[:github_repo]
|
143
|
+
|
144
|
+
puts "\n**** #{owner}/#{repo} ****\n"
|
145
|
+
|
146
|
+
full_diff = `heroku pipelines:diff -a #{app[:heroku_staging_app]}`
|
147
|
+
puts full_diff
|
148
|
+
revisions = full_diff.split("compare/").last.strip.split("...")
|
149
|
+
|
150
|
+
latest_commit = github_client.latest_remote_commit(owner: owner, repo: repo)
|
151
|
+
|
152
|
+
next if revisions.size < 2
|
153
|
+
|
154
|
+
if latest_commit != revisions.last
|
155
|
+
puts "WARNING - heroku staging app deploy is behind at commit #{revisions.last}. The repository is at commit #{latest_commit}"
|
156
|
+
end
|
157
|
+
|
158
|
+
puts formatted_deploy_notes(revisions.join('...'), owner: owner, repo: repo)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
121
162
|
desc "deploy_notes", "Generate Deploy notes for a range of commits"
|
122
163
|
method_option :commit_range, aliases: "-r", type: :string, required: true
|
123
164
|
|
124
165
|
def deploy_notes
|
166
|
+
puts formatted_deploy_notes(options[:commit_range], owner: github_client.get_repo_info[:owner], repo: github_client.get_repo_info[:repo])
|
125
167
|
puts formatted_deploy_notes
|
126
168
|
end
|
127
169
|
|
@@ -130,8 +172,13 @@ module GithubWorkflow
|
|
130
172
|
`/usr/bin/open -a "/Applications/Google Chrome.app" '#{url}'`
|
131
173
|
end
|
132
174
|
|
133
|
-
def create_branch
|
134
|
-
|
175
|
+
def create_branch(no_checkout = false)
|
176
|
+
if no_checkout
|
177
|
+
`git branch #{branch_name_for_issue_number} main`
|
178
|
+
else
|
179
|
+
`git checkout -b #{branch_name_for_issue_number} main`
|
180
|
+
end
|
181
|
+
say_info("created branch #{branch_name_for_issue_number}")
|
135
182
|
end
|
136
183
|
|
137
184
|
def ensure_origin_exists
|
@@ -170,6 +217,7 @@ module GithubWorkflow
|
|
170
217
|
issue_number_from_branch.to_i,
|
171
218
|
head: current_branch,
|
172
219
|
base: options[:base_branch] || "main",
|
220
|
+
draft: options[:draft],
|
173
221
|
).tap do |response|
|
174
222
|
if response["url"]
|
175
223
|
pass("Issue converted to Pull Request")
|
@@ -195,7 +243,13 @@ module GithubWorkflow
|
|
195
243
|
|
196
244
|
def branch_name_for_issue_number
|
197
245
|
issue = github_client.get_issue(issue_id)
|
198
|
-
"#{issue['number']}_#{issue['title'].strip.downcase.gsub(/[^a-zA-Z0-9]/, '_').squeeze("_")}"
|
246
|
+
branch_name ="#{issue['number']}_#{issue['title'].strip.downcase.gsub(/[^a-zA-Z0-9]/, '_').squeeze("_")}"
|
247
|
+
|
248
|
+
if options[:truncate_branch_at]
|
249
|
+
branch_name[0...options[:truncate_branch_at]]
|
250
|
+
else
|
251
|
+
branch_name
|
252
|
+
end
|
199
253
|
end
|
200
254
|
|
201
255
|
def github_client
|
@@ -245,35 +299,37 @@ module GithubWorkflow
|
|
245
299
|
`git branch`.gsub(" ", "").split("\n").select { |br| br.match /^[0-9]/ }
|
246
300
|
end
|
247
301
|
|
248
|
-
def
|
249
|
-
|
250
|
-
end
|
251
|
-
|
252
|
-
def pull_request_in_commit_range
|
253
|
-
pr_ids = commits_for_range["commits"].map do |commit|
|
302
|
+
def pull_request_in_commit_range(commits, owner:, repo:)
|
303
|
+
pr_ids = commits.map do |commit|
|
254
304
|
commit.dig("commit", "message").to_s.match(/(?<=\[#)\d{4,5}(?=\])/).to_s.to_i
|
255
305
|
end.uniq.compact
|
256
306
|
|
257
307
|
prs = pr_ids.map do |id|
|
258
308
|
say_info("Fetching Pull Request ##{id}")
|
259
|
-
pr = github_client.get_pr(id)
|
309
|
+
pr = github_client.get_pr(id, owner: owner, repo: repo)
|
260
310
|
|
261
311
|
next pr if pr["number"]
|
262
312
|
|
263
|
-
github_client.get_issue(id)
|
313
|
+
github_client.get_issue(id, owner: owner, repo: repo)
|
264
314
|
end
|
265
315
|
end
|
266
316
|
|
267
|
-
def formatted_deploy_notes
|
268
|
-
|
269
|
-
|
317
|
+
def formatted_deploy_notes(commit_range, owner:, repo:)
|
318
|
+
notes = pull_request_in_commit_range(
|
319
|
+
github_client.commits_for_range(commit_range, owner: owner, repo: repo)["commits"],
|
320
|
+
owner: owner,
|
321
|
+
repo: repo
|
322
|
+
).map do |pr|
|
323
|
+
deploy_note = pr["body"].to_s.split("**Deploy Note:**")[1].to_s.split(/\n/)[0].to_s.strip
|
270
324
|
|
271
|
-
if deploy_note.length >
|
272
|
-
"- #{deploy_note}"
|
273
|
-
else
|
274
|
-
%Q{Missing deploy note: #{pr["title"]}}
|
325
|
+
if deploy_note.length > 3
|
326
|
+
"- [##{pr["number"]}] #{deploy_note}"
|
275
327
|
end
|
276
|
-
end.
|
328
|
+
end.compact
|
329
|
+
|
330
|
+
notes = ['- No notes'] if notes.empty?
|
331
|
+
|
332
|
+
notes.unshift("[#{repo}]")
|
277
333
|
end
|
278
334
|
|
279
335
|
def success?(command)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Daisybill
|
2
|
+
APPS = [
|
3
|
+
DAISYBILL = {
|
4
|
+
"github_org": "daisybill",
|
5
|
+
"github_repo": "daisyBill",
|
6
|
+
"heroku_staging_app": "daisybill-staging"
|
7
|
+
},
|
8
|
+
ELLIS = {
|
9
|
+
"github_org": "daisybill",
|
10
|
+
"github_repo": "ellis",
|
11
|
+
"heroku_staging_app": "ellis-staging"
|
12
|
+
},
|
13
|
+
AUTH_INBOX = {
|
14
|
+
"github_org": "daisybill",
|
15
|
+
"github_repo": "auth-inbox",
|
16
|
+
"heroku_staging_app": "auth-inbox-staging"
|
17
|
+
},
|
18
|
+
KNOWLEDGEABLE = {
|
19
|
+
"github_org": "daisybill",
|
20
|
+
"github_repo": "knowledgeable",
|
21
|
+
"heroku_staging_app": "knowledgeable-staging"
|
22
|
+
},
|
23
|
+
FEE_SCHEDULE = {
|
24
|
+
"github_org": "daisybill",
|
25
|
+
"github_repo": "fee_schedule",
|
26
|
+
"heroku_staging_app": "fee-schedule-staging"
|
27
|
+
},
|
28
|
+
WCB_XML_CLEARINGHOUSE = {
|
29
|
+
"github_org": "daisybill",
|
30
|
+
"github_repo": "wcb_xml_clearinghouse",
|
31
|
+
"heroku_staging_app": "wcb-xml-clearinghouse-staging"
|
32
|
+
}
|
33
|
+
]
|
34
|
+
end
|
@@ -1,37 +1,56 @@
|
|
1
1
|
|
2
2
|
class GhCliClient
|
3
3
|
|
4
|
-
def get_issue(id)
|
5
|
-
request("'
|
4
|
+
def get_issue(id, owner: nil, repo: nil)
|
5
|
+
request("'#{path_base(owner, repo)}/issues/#{id}'")
|
6
6
|
end
|
7
7
|
|
8
|
-
def get_pr(id)
|
9
|
-
request("'
|
8
|
+
def get_pr(id, owner: nil, repo: nil)
|
9
|
+
request("'#{path_base(owner, repo)}/pulls/#{id}'")
|
10
10
|
end
|
11
11
|
|
12
|
-
def get_prs_list
|
13
|
-
request("'
|
12
|
+
def get_prs_list(owner: nil, repo: nil)
|
13
|
+
request("'#{path_base(owner, repo)}/pulls?per_page=100'")
|
14
14
|
end
|
15
15
|
|
16
|
-
def create_issue(title:, body: '')
|
17
|
-
request("'
|
16
|
+
def create_issue(title:, body: '', owner: nil, repo: nil)
|
17
|
+
request("'#{path_base(owner, repo)}/issues'", args: {title: title, body: body})
|
18
18
|
end
|
19
19
|
|
20
|
-
def convert_issue_to_pr(id, head:, base:)
|
21
|
-
request("'
|
20
|
+
def convert_issue_to_pr(id, head:, base:, owner: nil, repo: nil, draft: true)
|
21
|
+
request("'#{path_base(owner, repo)}/pulls'", args: {issue: id.to_i, head: head, base: base, draft: draft})
|
22
22
|
end
|
23
23
|
|
24
|
-
def commits_for_range(commit_range)
|
24
|
+
def commits_for_range(commit_range, owner: nil, repo: nil)
|
25
25
|
# https://docs.github.com/en/rest/commits/commits#compare-two-commits
|
26
|
-
request("'
|
26
|
+
request("'#{path_base(owner, repo)}/compare/#{commit_range}'")
|
27
27
|
end
|
28
28
|
|
29
|
-
def get_statuses(branch: '{branch}')
|
30
|
-
request("'
|
29
|
+
def get_statuses(branch: '{branch}', owner: nil, repo: nil)
|
30
|
+
request("'#{path_base(owner, repo)}/statuses/#{branch}'")
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_repo_info
|
34
|
+
@repo_info ||= begin
|
35
|
+
result = `gh repo view --json owner,name -q ".owner.login,.name"`.split("\n").compact
|
36
|
+
{
|
37
|
+
owner: result[0],
|
38
|
+
repo: result[1]
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def latest_remote_commit(owner:, repo:)
|
44
|
+
result = `gh browse -R '#{owner}/#{repo}' -n -c`
|
45
|
+
result.split("/").last.strip
|
31
46
|
end
|
32
47
|
|
33
48
|
protected
|
34
49
|
|
50
|
+
def path_base(owner, repo)
|
51
|
+
"repos/#{owner || "{owner}"}/#{repo || "{repo}"}"
|
52
|
+
end
|
53
|
+
|
35
54
|
def request(url, args: {})
|
36
55
|
arg_params = args.map{ |k,v| "-F '#{k}'='#{v}'" }.join(' ')
|
37
56
|
response = `gh api #{url} #{arg_params}`
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: github_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Liscio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- bin/github_workflow
|
97
97
|
- github_workflow.gemspec
|
98
98
|
- lib/github_workflow/cli.rb
|
99
|
+
- lib/github_workflow/daisybill.rb
|
99
100
|
- lib/github_workflow/gh_cli_client.rb
|
100
101
|
- lib/github_workflow/version.rb
|
101
102
|
homepage: https://github.com/daisybill/github_workflow
|
@@ -117,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
118
|
- !ruby/object:Gem::Version
|
118
119
|
version: '0'
|
119
120
|
requirements: []
|
120
|
-
rubygems_version: 3.
|
121
|
+
rubygems_version: 3.3.26
|
121
122
|
signing_key:
|
122
123
|
specification_version: 4
|
123
124
|
summary: DaisyBill's internal github workflows
|