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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e9f6a6dfe205f986f1d69b2a778ca8aaf008833423cbde6e664818d90c7c0e0
4
- data.tar.gz: 1f3dce21f39ca0e0ca4cba5ddcafa0c1817b2e0fd4d8e5ef2de82b6abd4a6f21
3
+ metadata.gz: 221999fe5304093bf6533718d5866ad58dc006af43945177f65e65d058dc6c8c
4
+ data.tar.gz: f48cea6b9a3a7588cc47f70ff257e54c4316edda6394df12cb3c25dfedb2f6de
5
5
  SHA512:
6
- metadata.gz: a4b8055a935171f2c1a9e694ada8ca0b78704e4c49f5880745f4c1920023841fcd94d1819a39bdd26bee89b35a1a6c508de49f16538b45bd261dad39b0798d97
7
- data.tar.gz: 824bc8e9cfadf38d68a9e6b34d22a715eeaa08c3dc260ce7637aef8e10f7cc89bfa2313992dd8a0619f88c4908207c68268c04551d3867e48c6de354ea0892e4
6
+ metadata.gz: 238cf09eaabe2ed9d28cd57d187f88a470a1e4614e188eb6ee709b16521848be294944c12f1571961baef940f3929e9a13bdeea0ee46c4ebff0cdd36ce4b3646
7
+ data.tar.gz: ea20ea5e64ff0432454c18d206bcffa3b448dd32c56e708e979de4a090875099c6737059fd9a5b8e1ad9a87482dc88a53786f2b4c76b6f593a16a54d834bb31a
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+
11
+ .DS_Store
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.4
1
+ 3.1.3
data/README.md CHANGED
@@ -1,26 +1,42 @@
1
1
  # Setup
2
2
 
3
- Install the [GitHub cli](https://cli.github.com/manual/)
3
+ ## GitHub CLI
4
4
 
5
+ Install instructions:
6
+
7
+ ### MacOS:
5
8
  `brew install gh`
6
9
 
7
- login to the cli
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
- `gh login`
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
- # Github Workflow
23
+ # Commands
12
24
 
13
25
  ```
14
26
  $ bin/github_workflow -h
15
27
 
16
28
  Commands:
17
- github_workflow create_and_start -m, --name=NAME # Create and start issue
18
- github_workflow create_pr # Convert Issue to Pull Request
19
- github_workflow help [COMMAND] # Describe available commands or one specific command
20
- github_workflow info # Print out issue description
21
- github_workflow open # Open issue or PR in browser
22
- github_workflow push_and_pr # Push branch to origin and convert Issue to Pull Request
23
- github_workflow start -i, --issue-id=ISSUE_ID # Create branch named with issue number and issue title
24
- github_workflow status # Check PR CI status
25
- github_workflow reviews # Print out reviewers list and their PRs count
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
  ```
@@ -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
- `git checkout -b #{branch_name_for_issue_number} main`
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 commits_for_range
249
- github_client.commits_for_range(options[:commit_range])
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
- pull_request_in_commit_range.map do |pr|
269
- deploy_note = pr["body"].to_s.split("**Deploy Note:**")[1].to_s.split(/\n/)[0].to_s
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 > 0
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.unshift("[DaisyBill]")
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("'repos/{owner}/{repo}/issues/#{id}'")
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("'repos/{owner}/{repo}/pulls/#{id}'")
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("'repos/{owner}/{repo}/pulls?per_page=100'")
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("'repos/{owner}/{repo}/issues'", args: {title: title, body: body})
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("'repos/{owner}/{repo}/pulls'", args: {issue: id.to_i, head: head, base: base})
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("'repos/{owner}/{repo}/compare/#{commit_range}'")
26
+ request("'#{path_base(owner, repo)}/compare/#{commit_range}'")
27
27
  end
28
28
 
29
- def get_statuses(branch: '{branch}')
30
- request("'repos/{owner}/{repo}/statuses/#{branch}'")
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}`
@@ -1,3 +1,3 @@
1
1
  module GithubWorkflow
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.3"
3
3
  end
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.0
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: 2022-05-24 00:00:00.000000000 Z
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.1.6
121
+ rubygems_version: 3.3.26
121
122
  signing_key:
122
123
  specification_version: 4
123
124
  summary: DaisyBill's internal github workflows