class GithubWorkflow::Cli
Constants
- GITHUB_CONFIG
- PROCEED_TEXT
Public Instance Methods
alert(message)
click to toggle source
# File lib/github_workflow/cli.rb, line 447 def alert(message) say_status("ALERT", message, :red) end
branch_name_for_issue_number()
click to toggle source
# File lib/github_workflow/cli.rb, line 350 def branch_name_for_issue_number issue = JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{issue_id}").body) "#{issue['number']}_#{issue['title'].strip.downcase.gsub(/[^a-zA-Z0-9]/, '_').squeeze("_")}" end
cleanup()
click to toggle source
# File lib/github_workflow/cli.rb, line 126 def cleanup say_info("Checking merge status") merged_pr_branches puts "\n" if merged_pr_branches.any? say_info("Are you sure you want to delete the branches with checkmarks?") if yes?(PROCEED_TEXT) pass("Deleting Branches") merged_pr_branches.each do |branch| `git branch -D #{branch}` end else failure("Cleanup aborted") end else failure("No merged branches to delete") end end
commits_for_range()
click to toggle source
# File lib/github_workflow/cli.rb, line 406 def commits_for_range JSON.parse(github_client.get("repos/#{user_and_repo}/compare/#{options[:commit_range]}").body) end
convert_issue_to_pr()
click to toggle source
# File lib/github_workflow/cli.rb, line 317 def convert_issue_to_pr github_client.post( "repos/#{user_and_repo}/pulls", JSON.generate( { head: current_branch, base: options[:base_branch] || "main", issue: issue_number_from_branch.to_i } ) ).tap do |response| if response.success? pass("Issue converted to Pull Request") say_info(JSON.parse(response.body)["url"]) else alert("An error occurred when creating PR:") alert("#{response.status}: #{JSON.parse(response.body)['message']}") end end end
create_and_start()
click to toggle source
# File lib/github_workflow/cli.rb, line 120 def create_and_start ensure_github_config_present create_issue end
create_branch()
click to toggle source
# File lib/github_workflow/cli.rb, line 185 def create_branch `git checkout -b #{branch_name_for_issue_number} main` end
create_issue()
click to toggle source
# File lib/github_workflow/cli.rb, line 293 def create_issue github_client.post( "repos/#{user_and_repo}/issues", JSON.generate( { title: options[:name] } ) ).tap do |response| if response.success? pass("Issue created") @issue_id = JSON.parse(response.body)["number"] start else alert("An error occurred when creating issue:") alert("#{response.status}: #{JSON.parse(response.body)['message']}") end end end
create_issue_from_trello_card()
click to toggle source
# File lib/github_workflow/cli.rb, line 197 def create_issue_from_trello_card say_info("Creating issue") issue_params = { title: trello_card.name, body: issue_body_from_trello_card, assignees: [current_github_username], labels: trello_card.labels.map(&:name) } response = JSON.parse(github_client.post("repos/#{user_and_repo}/issues", issue_params.to_json).body) @issue_id = response["number"] github_client.post("/repos/#{user_and_repo}/issues/#{@issue_id}/comments", { body: trello_card.short_url }.to_json) trello_card.add_attachment response["html_url"] end
create_pr()
click to toggle source
# File lib/github_workflow/cli.rb, line 67 def create_pr ensure_github_config_present ensure_origin_exists convert_issue_to_pr end
current_branch()
click to toggle source
# File lib/github_workflow/cli.rb, line 346 def current_branch `git rev-parse --abbrev-ref HEAD`.chomp end
current_github_username()
click to toggle source
# File lib/github_workflow/cli.rb, line 243 def current_github_username JSON.parse(github_client.get("user").body)["login"] end
deploy_notes()
click to toggle source
# File lib/github_workflow/cli.rb, line 168 def deploy_notes puts formatted_deploy_notes end
ensure_github_config_present()
click to toggle source
# File lib/github_workflow/cli.rb, line 264 def ensure_github_config_present if project_config.nil? || (JSON.parse(GITHUB_CONFIG).keys - project_config.keys).any? failure("Please add `.github_workflow` file containing:\n#{GITHUB_CONFIG}") end end
ensure_origin_exists()
click to toggle source
# File lib/github_workflow/cli.rb, line 189 def ensure_origin_exists Open3.capture2("git rev-parse --abbrev-ref --symbolic-full-name @{u}").tap do |_, status| unless status.success? failure("Upstream branch does not exist. Please set before creating pull request. E.g., `git push -u origin branch_name`") end end end
failure(message)
click to toggle source
# File lib/github_workflow/cli.rb, line 459 def failure(message) say_status("FAIL", message, :red) exit end
formatted_deploy_notes()
click to toggle source
# File lib/github_workflow/cli.rb, line 427 def formatted_deploy_notes pull_request_in_commit_range.map do |pr| deploy_note = pr["body"].to_s.split("**Deploy Note:**")[1].to_s.split(/\n/)[0].to_s if deploy_note.length > 0 "- #{deploy_note}" else %Q{Missing deploy note: #{pr["title"]}} end end.unshift("[DaisyBill]") end
get_issue(id)
click to toggle source
# File lib/github_workflow/cli.rb, line 173 def get_issue(id) JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{id}").body) end
get_pr(id)
click to toggle source
# File lib/github_workflow/cli.rb, line 177 def get_pr(id) JSON.parse(github_client.get("repos/#{user_and_repo}/pulls/#{id}").body) end
get_prs_list()
click to toggle source
# File lib/github_workflow/cli.rb, line 181 def get_prs_list JSON.parse(github_client.get("repos/#{user_and_repo}/pulls?per_page=100").body) end
github_client()
click to toggle source
# File lib/github_workflow/cli.rb, line 355 def github_client Faraday.new(url: "https://api.github.com") do |faraday| faraday.request :url_encoded faraday.adapter Faraday.default_adapter faraday.authorization :Bearer, oauth_token end end
info()
click to toggle source
# File lib/github_workflow/cli.rb, line 106 def info ensure_github_config_present puts get_issue(issue_number_from_branch)["body"] end
init_trello()
click to toggle source
# File lib/github_workflow/cli.rb, line 270 def init_trello Trello.configure do |config| config.developer_public_key = project_config["trello_key"] config.member_token = project_config["trello_token"] end end
issue_body_from_trello_card()
click to toggle source
# File lib/github_workflow/cli.rb, line 215 def issue_body_from_trello_card [trello_card.desc, trello_deploy_note, trello_product_review_type, trello_pm].compact.join("\n\n") end
issue_id()
click to toggle source
# File lib/github_workflow/cli.rb, line 313 def issue_id @issue_id ||= options[:issue_id] end
issue_number_from_branch()
click to toggle source
# File lib/github_workflow/cli.rb, line 338 def issue_number_from_branch current_branch.split("_").first.tap do |issue_number| if !issue_number failure("Unable to parse issue number from branch. Are you sure you have a branch checked out?") end end end
merged_pr_branches()
click to toggle source
# File lib/github_workflow/cli.rb, line 391 def merged_pr_branches @merged_pr_branches ||= pr_branches.map do |branch| id = branch.split("_")[0].to_i merged = !!get_pr(id)["merged"] print merged ? "✅ " : "❌ " puts " #{branch}" merged ? branch : nil end.compact end
oauth_token()
click to toggle source
# File lib/github_workflow/cli.rb, line 281 def oauth_token project_config["oauth_token"] end
open()
click to toggle source
# File lib/github_workflow/cli.rb, line 112 def open ensure_github_config_present response = JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{issue_number_from_branch}").body) `/usr/bin/open -a "/Applications/Google Chrome.app" '#{response["html_url"]}'` end
pass(message)
click to toggle source
# File lib/github_workflow/cli.rb, line 455 def pass(message) say_status("OK", message, :green) end
platform()
click to toggle source
# File lib/github_workflow/cli.rb, line 44 def platform ensure_github_config_present init_trello set_trello_card(type: :platform) create_issue_from_trello_card stash rebase_main create_branch stash_pop end
pr_branches()
click to toggle source
# File lib/github_workflow/cli.rb, line 402 def pr_branches `git branch`.gsub(" ", "").split("\n").select { |br| br.match /^[0-9]/ } end
project_config()
click to toggle source
# File lib/github_workflow/cli.rb, line 277 def project_config @project_config ||= JSON.parse(File.read(".github_workflow")) rescue nil end
pull_request_in_commit_range()
click to toggle source
# File lib/github_workflow/cli.rb, line 410 def pull_request_in_commit_range pr_ids = commits_for_range["commits"].map do |commit| commit.dig("commit", "message").to_s.match(/(?<=\[#)\d{4,5}(?=\])/).to_s.to_i end.uniq.compact prs = pr_ids.map do |id| say_info("Fetching Pull Request ##{id}") pr = github_client.get("repos/#{user_and_repo}/pulls/#{id}") if pr.status == 404 JSON.parse(github_client.get("repos/#{user_and_repo}/issues/#{id}").body) else JSON.parse(pr.body) end end end
push_and_pr()
click to toggle source
# File lib/github_workflow/cli.rb, line 75 def push_and_pr ensure_github_config_present push_and_set_upstream convert_issue_to_pr end
push_and_set_upstream()
click to toggle source
# File lib/github_workflow/cli.rb, line 289 def push_and_set_upstream `git rev-parse --abbrev-ref HEAD | xargs git push origin -u` end
rebase_main()
click to toggle source
# File lib/github_workflow/cli.rb, line 363 def rebase_main say_info("Fetching changes and rebasing main") if success?("git pull origin main:main --rebase") pass("Fetched and rebased") else failure("Failed to fetch or rebase") end end
reviews()
click to toggle source
# File lib/github_workflow/cli.rb, line 149 def reviews ensure_github_config_present reviewers = get_prs_list.map { |pr| pr["requested_reviewers"].map { |r| r["login"] } }.flatten reviewer_counts = reviewers.group_by { |i| i }.map { |k, v| [k, v.count] } if reviewer_counts.any? table = Terminal::Table.new(style: { width: 50 }) do |table_rows| table_rows << ["Username", "Requested PRs Count"] table_rows << :separator reviewer_counts.each { |reviewer_count| table_rows << reviewer_count } end puts table end end
say_info(message)
click to toggle source
# File lib/github_workflow/cli.rb, line 451 def say_info(message) say_status("INFO", message, :black) end
set_trello_card(type:)
click to toggle source
# File lib/github_workflow/cli.rb, line 247 def set_trello_card(type:) say_info("Fetching trello card") trello_board = if type Trello::Board.find(project_config["trello_#{type}_board_id"]) else Trello::Board.find(project_config["trello_board_id"]) end @trello_card = trello_board.find_card(options["card_number"].to_i) end
start()
click to toggle source
# File lib/github_workflow/cli.rb, line 57 def start ensure_github_config_present stash rebase_main create_branch stash_pop end
stash()
click to toggle source
# File lib/github_workflow/cli.rb, line 373 def stash `git diff --quiet` if !$?.success? say_info("Stashing local changes") `git stash --quiet` @stashed = true end end
stash_pop()
click to toggle source
# File lib/github_workflow/cli.rb, line 383 def stash_pop if @stashed say_info("Stash pop") `git stash pop` nil end end
status()
click to toggle source
# File lib/github_workflow/cli.rb, line 82 def status ensure_github_config_present ensure_origin_exists response = JSON.parse(github_client.get("repos/#{user_and_repo}/statuses/#{current_branch}").body) if response.empty? alert "No statuses yet. Have you pushed your branch?" else table = Terminal::Table.new(style: { width: 80 }) do |table_rows| table_rows << %w(CI Status Description) table_rows << :separator response.map { |status| status["context"] }.uniq.map do |status| response.select { |st| st["context"] == status }.sort_by { |st| st["updated_at"] }.last end.each do |status| table_rows << %w(context state description).map { |key| status[key] } end end puts table end end
success?(command)
click to toggle source
# File lib/github_workflow/cli.rb, line 439 def success?(command) IO.popen(command) do |output| output.each { |line| puts line } end $?.success? end
trello()
click to toggle source
# File lib/github_workflow/cli.rb, line 31 def trello ensure_github_config_present init_trello set_trello_card(type: nil) create_issue_from_trello_card stash rebase_main create_branch stash_pop end
trello_card()
click to toggle source
# File lib/github_workflow/cli.rb, line 260 def trello_card @trello_card end
trello_deploy_note()
click to toggle source
# File lib/github_workflow/cli.rb, line 227 def trello_deploy_note custom_field = trello_card.custom_field_items.detect { |cfi| cfi.custom_field.name == "Deploy Note" } if custom_field.present? "**Deploy Note:** #{custom_field.value['text']}" end end
trello_pm()
click to toggle source
# File lib/github_workflow/cli.rb, line 219 def trello_pm custom_field = trello_card.custom_field_items.detect { |cfi| cfi.custom_field.name == "PM" } if custom_field.present? "**Responsible:** #{custom_field.option_value['text']}" end end
trello_product_review_type()
click to toggle source
# File lib/github_workflow/cli.rb, line 235 def trello_product_review_type custom_field = trello_card.custom_field_items.detect { |cfi| cfi.custom_field.name == "Product Review" } if custom_field.present? "**Product Review:** #{custom_field.option_value['text']}" end end
user_and_repo()
click to toggle source
# File lib/github_workflow/cli.rb, line 285 def user_and_repo project_config["user_and_repo"] end