Enable uploadpack allow-SHA1-in-want for CI checkout

e60ba65 · gmorell · 2026-06-25 15:34

2 files +60 -0
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud/release.ex
+36 −0
@@ -44,6 +44,42 @@ defmodule GitGud.Release do
44 44 IO.write(pub_pem)
45 45 end
46 46
47 + @doc """
48 + Backfill the per-repo git config that CI clients need — `actions/checkout`
49 + (and any `git fetch --depth=1 <sha>`) asks the server to `want` a
50 + specific commit SHA, which git refuses ("Server does not allow request
51 + for unadvertised object") unless `uploadpack.allow*SHA1InWant` is set.
52 + New repos get this at creation; this fixes ones created before it.
53 +
54 + Run in a deployed pod (no Mix in a release):
55 +
56 + kubectl -n git-gud exec deployment/git-gud -- \\
57 + bin/git_gud eval 'GitGud.Release.configure_repos()'
58 +
59 + Idempotent.
60 + """
61 + def configure_repos do
62 + load_app()
63 +
64 + {:ok, {ok, skipped}, _} =
65 + Ecto.Migrator.with_repo(GitGud.Repo, fn _repo ->
66 + import Ecto.Query, warn: false
67 +
68 + GitGud.Repo.all(from(r in GitGud.Repositories.Repository, select: r.disk_path))
69 + |> Enum.reduce({0, 0}, fn disk_path, {ok, skipped} ->
70 + if is_binary(disk_path) and File.dir?(disk_path) do
71 + GitGud.Repositories.configure_git(disk_path)
72 + {ok + 1, skipped}
73 + else
74 + {ok, skipped + 1}
75 + end
76 + end)
77 + end)
78 +
79 + IO.puts("configured #{ok} repo(s); #{skipped} skipped (missing disk_path/dir)")
80 + :ok
81 + end
82 +
47 83 defp repos do
48 84 Application.fetch_env!(@app, :ecto_repos)
49 85 end
modified lib/git_gud/repositories.ex
+24 −0
@@ -558,6 +558,7 @@ defmodule GitGud.Repositories do
558 558 case init_function(fk).(disk_path) do
559 559 :ok ->
560 560 install_hooks(disk_path)
561 + configure_git(disk_path)
561 562 repo
562 563
563 564 {:error, reason} ->
@@ -857,6 +858,29 @@ defmodule GitGud.Repositories do
857 858 install_hook(disk_path, "pre-receive", "gitgud-prereceive")
858 859 end
859 860
861 + @doc """
862 + Per-repo git config required for CI. `actions/checkout` (and any
863 + `git fetch --depth=1 <sha>`) asks the server to `want` a specific
864 + commit SHA; vanilla git refuses unadvertised objects with "Server does
865 + not allow request for unadvertised object". Enabling
866 + `uploadpack.allowReachableSHA1InWant` (+ `allowAnySHA1InWant`) permits
867 + it, matching what Gitea/Forgejo set on Actions-enabled repos.
868 +
869 + Idempotentsafe to call on existing repos (see the
870 + `gitgud.repos.configure` mix task for backfilling).
871 + """
872 + def configure_git(disk_path) do
873 + for {k, v} <- [
874 + {"uploadpack.allowAnySHA1InWant", "true"},
875 + {"uploadpack.allowReachableSHA1InWant", "true"},
876 + {"uploadpack.allowTipSHA1InWant", "true"}
877 + ] do
878 + System.cmd("git", ["-C", disk_path, "config", k, v], stderr_to_stdout: true)
879 + end
880 +
881 + :ok
882 + end
883 +
860 884 defp install_hook(disk_path, name, default_bin) do
861 885 hook_path = Path.join([disk_path, "hooks", name])
862 886 bridge = script_path(default_bin)

Parents: 5e67fc0