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
54 changes: 54 additions & 0 deletions lib/hypatia/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ defmodule Hypatia.CLI do
hypatia pr-eligibility --owner X Query AM010 admin-merge eligibility for a PR
--repo Y
--pr N
hypatia secret-alerts --owner X Secret-scanning alerts for one repo, as one JSON line
--repo Y (exit 3 if they cannot be fetched)
hypatia version Print version and exit
hypatia help Print usage and exit

Expand Down Expand Up @@ -155,6 +157,9 @@ defmodule Hypatia.CLI do
["pr-eligibility" | _] ->
run_pr_eligibility(opts[:owner], opts[:repo], opts[:pr])

["secret-alerts" | _] ->
run_secret_alerts(opts[:owner], opts[:repo])

["version"] ->
IO.puts("hypatia #{@version}")

Expand Down Expand Up @@ -284,6 +289,50 @@ defmodule Hypatia.CLI do
System.halt(2)
end

# ─── Secret-scanning alerts for one repo (estate sweep) ──────────────

@doc false
def run_secret_alerts(owner, repo) when is_binary(owner) and is_binary(repo) do
{line, exit_code} = secret_alerts_output(owner, repo)
IO.puts(line)
if exit_code != 0, do: System.halt(exit_code)
end

def run_secret_alerts(_, _) do
IO.puts(:stderr, "Error: secret-alerts requires --owner and --repo.")
IO.puts(:stderr, "Usage: hypatia secret-alerts --owner OWNER --repo REPO")
System.halt(2)
end

@doc false
# One JSON line, and the exit code to return: 0 when the alerts were read
# (with or without findings), 3 when they could not be. A sweep must be
# able to tell "no alerts" from "could not look", so a refused token or a
# repo with secret scanning disabled is never reported as clean.
def secret_alerts_output(
owner,
repo,
sweep \\ &Hypatia.Rules.SecretScanningAlerts.sweep/2
) do
case sweep.(owner, repo) do
{:ok, result} ->
line =
Jason.encode!(%{
owner: owner,
repo: repo,
status: "ok",
total: result.total,
by_severity: result.by_severity,
findings: result.findings
})

{line, 0}

{:error, reason} ->
{Jason.encode!(%{owner: owner, repo: repo, status: "error", error: reason}), 3}
end
end

# ─── Diagnostic summary ──────────────────────────────────────────────
#
# Always emit a single-line summary on stderr after a scan/report so CI
Expand Down Expand Up @@ -1578,6 +1627,11 @@ defmodule Hypatia.CLI do
--owner OWNER GitHub owner (org or user)
--repo REPO Repository name
--pr NUMBER PR number
secret-alerts Secret-scanning alerts for one repo (one JSON line)
--owner OWNER GitHub owner (org or user)
--repo REPO Repository name
Token: HYPATIA_SECRET_ALERTS_TOKEN, else GITHUB_TOKEN.
Exit 3 when the alerts cannot be fetched.
version Show version
help Show this help

Expand Down
Loading
Loading