defmodule GitGud.Release do
@moduledoc """
Used for executing DB release tasks when run in production without Mix
installed.
"""
@app :git_gud
def migrate do
load_app()
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
def rollback(repo, version) do
load_app()
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
end
@doc """
Mint an RS256 keypair for the OCI registry token endpoint and print
both PEMs to stdout with `===PRIV===` / `===PUB===` delimiters.
Use from inside a running pod when you don't want key material on
your laptop:
kubectl -n git-gud exec deployment/git-gud -- \\
bin/git_gud eval 'GitGud.Release.keygen()'
Pipe the output through `awk` (see operator runbook) to split the
two PEMs and feed them directly into `kubectl create secret` /
`kubectl patch secret` without ever touching the local filesystem.
"""
def keygen(bits \\ 4096) do
Application.ensure_all_started(:crypto)
Application.ensure_all_started(:public_key)
{priv_pem, pub_pem} = GitGud.Packages.Token.generate_keypair(bits)
IO.write("===PRIV===\n")
IO.write(priv_pem)
IO.write("===PUB===\n")
IO.write(pub_pem)
end
@doc """
Backfill the per-repo git config that CI clients need — `actions/checkout`
(and any `git fetch --depth=1 <sha>`) asks the server to `want` a
specific commit SHA, which git refuses ("Server does not allow request
for unadvertised object") unless `uploadpack.allow*SHA1InWant` is set.
New repos get this at creation; this fixes ones created before it.
Run in a deployed pod (no Mix in a release):
kubectl -n git-gud exec deployment/git-gud -- \\
bin/git_gud eval 'GitGud.Release.configure_repos()'
Idempotent.
"""
def configure_repos do
load_app()
{:ok, {ok, skipped}, _} =
Ecto.Migrator.with_repo(GitGud.Repo, fn _repo ->
import Ecto.Query, warn: false
GitGud.Repo.all(from(r in GitGud.Repositories.Repository, select: r.disk_path))
|> Enum.reduce({0, 0}, fn disk_path, {ok, skipped} ->
if is_binary(disk_path) and File.dir?(disk_path) do
GitGud.Repositories.configure_git(disk_path)
{ok + 1, skipped}
else
{ok, skipped + 1}
end
end)
end)
IO.puts("configured #{ok} repo(s); #{skipped} skipped (missing disk_path/dir)")
:ok
end
@doc """
Send a test event to Sentry to verify the DSN + integration:
kubectl -n git-gud exec deployment/git-gud -- \\
bin/git_gud eval 'GitGud.Release.sentry_test()'
Sends synchronously (`result: :sync`) so the eval node doesn't exit
before delivery. Returns `{:ok, id}` on success, `{:error, _}` on a
transport failure, or `:ignored` when no DSN is configured.
"""
def sentry_test do
{:ok, _} = Application.ensure_all_started(:sentry)
result =
Sentry.capture_message("git_gud Sentry test event (Release.sentry_test/0)",
level: :error,
result: :sync
)
IO.inspect(result, label: "sentry_test")
result
end
defp repos do
Application.fetch_env!(@app, :ecto_repos)
end
defp load_app do
# Many platforms require SSL when connecting to the database
Application.ensure_all_started(:ssl)
Application.ensure_loaded(@app)
end
end
3.4 KiB · text
5af55d9