Add Pulls to the repo header with an open count; refuse no-op PRs

719deae · Gabriel Morell · 2026-09-09 21:06

34 files +320 -98
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud/pull_requests.ex
+34 −1
@@ -51,6 +51,13 @@ defmodule GitGud.PullRequests do
51 51 Enum.map(prs, &Map.put(&1, :labels, Map.get(labels_by_id, &1.id, [])))
52 52 end
53 53
54 + @doc "How many pull requests are open against this repo."
55 + def count_open(%Repository{id: rid}) do
56 + PullRequest
57 + |> where([p], p.repository_id == ^rid and p.state == "open")
58 + |> Repo.aggregate(:count)
59 + end
60 +
54 61 defp filter_state(q, "all"), do: q
55 62
56 63 defp filter_state(q, s) when s in ["open", "closed", "merged"],
@@ -118,7 +125,14 @@ defmodule GitGud.PullRequests do
118 125 # the target's object database before merge_base / merge_tree
119 126 # can see both SHAs from one repo's perspective.
120 127 :ok <- maybe_fetch_cross_repo(cross_repo?, repo, source_repo, source_ref),
121 {:ok, base_sha} <- Git.merge_base(repo.disk_path, head_sha, target_sha) do
128 + {:ok, base_sha} <- Git.merge_base(repo.disk_path, head_sha, target_sha),
129 + :ok <-
130 + ensure_something_to_merge(
131 + head_sha,
132 + target_sha,
133 + base_sha,
134 + not cross_repo? and source_ref == target_ref
135 + ) do
122 136 Repo.transaction(fn ->
123 137 next = Numbering.next_for(repo.id)
124 138
@@ -152,6 +166,9 @@ defmodule GitGud.PullRequests do
152 166 end
153 167 end)
154 168 else
169 + # Don't re-wrap what is already an error tuple — callers were
170 + # getting `{:error, {:error, :no_such_ref}}`.
171 + {:error, reason} -> {:error, reason}
155 172 err -> {:error, err}
156 173 end
157 174
@@ -330,6 +347,22 @@ defmodule GitGud.PullRequests do
330 347 )
331 348 end
332 349
350 + # Nothing to open a PR for when the two tips are the same commit, or
351 + # when the head is already an ancestor of the base — the merge-base
352 + # being the head itself means the base already contains every commit
353 + # the head has.
354 + # A branch onto itself is the changeset's business — it has a precise
355 + # message for that, and it renders on the field rather than as a flash.
356 + defp ensure_something_to_merge(_head, _target, _base, true), do: :ok
357 +
358 + defp ensure_something_to_merge(head_sha, target_sha, base_sha, _same_ref?) do
359 + cond do
360 + head_sha == target_sha -> {:error, :no_changes}
361 + head_sha == base_sha -> {:error, :no_changes}
362 + true -> :ok
363 + end
364 + end
365 +
333 366 defp resolve_source_repo(target_repo, nil), do: {target_repo, false}
334 367
335 368 defp resolve_source_repo(target_repo, id) when is_integer(id) or is_binary(id) do
modified lib/git_gud_web/live/branch_protection_live/index.ex
+8 −1
@@ -67,10 +67,17 @@ defmodule GitGudWeb.BranchProtectionLive.Index do
67 67 has_packages?={@has_packages?}
68 68 can_admin?={@can_admin?}
69 69 latest_run={@latest_run}
70 + open_pulls={@open_pulls}
70 71 />
71 72 <.repo_settings_header handle={@handle} repo={@repo} current={:branches} />
72 73
73 <.form for={@form} id="bp-form" phx-change="validate" phx-submit="add" class="space-y-3 max-w-2xl">
74 + <.form
75 + for={@form}
76 + id="bp-form"
77 + phx-change="validate"
78 + phx-submit="add"
79 + class="space-y-3 max-w-2xl"
80 + >
74 81 <.input
75 82 field={@form[:pattern]}
76 83 label="Pattern (glob)"
modified lib/git_gud_web/live/deploy_key_live/index.ex
+1 −0
@@ -67,6 +67,7 @@ defmodule GitGudWeb.DeployKeyLive.Index do
67 67 has_packages?={@has_packages?}
68 68 can_admin?={@can_admin?}
69 69 latest_run={@latest_run}
70 + open_pulls={@open_pulls}
70 71 />
71 72 <.repo_settings_header handle={@handle} repo={@repo} current={:deploy_keys} />
72 73
modified lib/git_gud_web/live/interaction_policy_live/edit.ex
+1 −0
@@ -54,6 +54,7 @@ defmodule GitGudWeb.InteractionPolicyLive.Edit do
54 54 has_packages?={@has_packages?}
55 55 can_admin?={@can_admin?}
56 56 latest_run={@latest_run}
57 + open_pulls={@open_pulls}
57 58 />
58 59 <.repo_settings_header handle={@handle} repo={@repo} current={:interaction} />
59 60
modified lib/git_gud_web/live/issue_live/index.ex
+1 −0
@@ -67,6 +67,7 @@ defmodule GitGudWeb.IssueLive.Index do
67 67 has_packages?={@has_packages?}
68 68 can_admin?={@can_admin?}
69 69 latest_run={@latest_run}
70 + open_pulls={@open_pulls}
70 71 />
71 72
72 73 <header class="flex items-center justify-between">
modified lib/git_gud_web/live/issue_live/new.ex
+2 −2

Click to load diff…

modified lib/git_gud_web/live/issue_live/show.ex
+6 −4

Click to load diff…

modified lib/git_gud_web/live/label_live/index.ex
+11 −4

Click to load diff…

modified lib/git_gud_web/live/pr_live/index.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/pr_live/new.ex
+9 −0

Click to load diff…

modified lib/git_gud_web/live/pr_live/show.ex
+10 −5

Click to load diff…

modified lib/git_gud_web/live/registry_token_live/index.ex
+33 −12

Click to load diff…

modified lib/git_gud_web/live/repo_live/blob.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/commit.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/committers.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/compare.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/fork.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/forks.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/header.ex
+16 −2

Click to load diff…

modified lib/git_gud_web/live/repo_live/languages.ex
+3 −3

Click to load diff…

modified lib/git_gud_web/live/repo_live/log.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/packages.ex
+8 −2

Click to load diff…

modified lib/git_gud_web/live/repo_live/settings.ex
+2 −3

Click to load diff…

modified lib/git_gud_web/live/repo_live/settings_runners.ex
+14 −6

Click to load diff…

modified lib/git_gud_web/live/repo_live/show.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/repo_live/tree.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/secrets_live/repo.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/webhook_live/index.ex
+8 −1

Click to load diff…

modified lib/git_gud_web/live/wiki_live/edit.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/wiki_live/index.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/wiki_live/show.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/workflow_live/index.ex
+1 −0

Click to load diff…

modified lib/git_gud_web/live/workflow_live/show.ex
+58 −50

Click to load diff…

modified test/git_gud_web/live/pr_live/new_cross_repo_test.exs
+80 −2

Click to load diff…

Parents: 6e19be9