Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def handle_open(action)
)
end

@gh.ensure_labels(@labels)
@git.checkout_fresh_branch(branch: spec.branch, base: @base)
committed = pin_packages_and_commit(spec)
if !committed
Expand Down
30 changes: 30 additions & 0 deletions lib/gh_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,23 @@ def create_pr(branch:, base:, title:, body:, labels: [])
result.stdout.strip[%r{/pull/(\d+)}, 1]&.to_i
end

# Ensures every label in +labels+ exists in the repo, creating any that
# are missing. Called once before opening PRs so that `create_pr` never
# fails with "label does not exist". Missing labels are created with a
# neutral default color; existing labels are left untouched.
def ensure_labels(labels)
return if labels.empty?
existing = list_label_names
labels.each do |label|
next if existing.include?(label)
@runner.run(
"gh", "label", "create", label,
"--repo", @repo,
"--color", "0075ca"
)
end
end

# Edits an existing PR's title and body. Used after force-pushing a
# changed branch — the body must be re-rendered so the metadata
# block reflects the new package set.
Expand Down Expand Up @@ -98,6 +115,19 @@ def close_pr(number:, comment: nil)

private

def list_label_names
result = @runner.run(
"gh", "label", "list",
"--repo", @repo,
"--json", "name",
"--limit", "200"
)
return [] unless result.success?
JSON.parse(result.stdout.force_encoding("UTF-8")).map { |l| l["name"] }
rescue JSON::ParserError
[]
end

def parse_pr_list(stdout, branch_prefix)
parsed = JSON.parse(stdout.force_encoding("UTF-8"))
# `head:foo/` is a *search* term, not a strict filter — GitHub's
Expand Down
3 changes: 3 additions & 0 deletions test/executor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def initialize
@next_pr_number = 1000
end

def ensure_labels(labels)
end

def create_pr(branch:, base:, title:, body:, labels: [])
@created << {branch: branch, base: base, title: title, body: body, labels: labels}
n = @next_pr_number
Expand Down
43 changes: 43 additions & 0 deletions test/gh_client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,49 @@ def test_list_open_prs_propagates_gh_failure
assert_includes err.message, "auth required"
end

# ---- ensure_labels ----

def test_ensure_labels_is_a_no_op_when_labels_is_empty
@client.ensure_labels([])
assert_equal 0, @runner.calls.size
end

def test_ensure_labels_creates_missing_labels
@runner.add(
pattern: ["gh", "label", "list", "--repo", REPO, "--json", "name", "--limit", "200"],
stdout: +%([{"name":"dependencies"}])
)
@runner.add(
pattern: ["gh", "label", "create", "javascript", "--repo", REPO, "--color", "0075ca"],
stdout: +""
)
@client.ensure_labels(%w[dependencies javascript])
assert_equal 2, @runner.calls.size
end

def test_ensure_labels_skips_labels_that_already_exist
@runner.add(
pattern: ["gh", "label", "list", "--repo", REPO, "--json", "name", "--limit", "200"],
stdout: +%([{"name":"dependencies"},{"name":"javascript"}])
)
@client.ensure_labels(%w[dependencies javascript])
assert_equal 1, @runner.calls.size
end

def test_ensure_labels_tolerates_gh_label_list_failure
@runner.add(
pattern: ["gh", "label", "list", "--repo", REPO, "--json", "name", "--limit", "200"],
stderr: "not found",
exit_code: 1
)
@runner.add(
pattern: ["gh", "label", "create", "dependencies", "--repo", REPO, "--color", "0075ca"],
stdout: +""
)
@client.ensure_labels(%w[dependencies])
assert_equal 2, @runner.calls.size
end

# ---- create_pr ----

def test_create_pr_invokes_gh_with_title_body_branch_and_base
Expand Down
Loading