Current section
Files
Jump to
Current section
Files
lib/flaky/cli.ex
defmodule Flaky.CLI do
@moduledoc """
Command-line interface for the flaky test detector.
"""
@help """
Detects new tests in git diff (HEAD vs main) and runs them repeatedly to catch flaky tests.
Usage:
flaky [options]
Options:
-n, --iterations N Number of times to repeat each test (default: 100)
-b, --base BRANCH Base branch to compare against (default: main)
-s, --seed SEED Specific seed for reproducibility
--dry-run Show which tests would be run without running them
-p, --parallel N Run tests in parallel with N concurrent processes
-m, --mix Distribute tests in batches across workers (with -p) or run all together (sequential)
-f, --failed Re-run only previously failed tests
-l, --print-full-log Show full error logs (default: 10 lines)
-q, --quiet Suppress error snippets and limit test list to 10
-w, --watch-errors Tail error log file in real-time
-h, --help Show this help message
Examples:
flaky
flaky --iterations 50
flaky --base develop
flaky --seed 12345 --iterations 200
flaky --dry-run
flaky --parallel 3
flaky -p 5 --mix
flaky --failed
flaky --print-full-log
"""
@switches [
iterations: :integer,
base: :string,
seed: :integer,
dry_run: :boolean,
parallel: :integer,
mix: :boolean,
failed: :boolean,
print_full_log: :boolean,
quiet: :boolean,
watch_errors: :boolean,
help: :boolean
]
@aliases [
n: :iterations,
b: :base,
s: :seed,
p: :parallel,
m: :mix,
f: :failed,
l: :print_full_log,
q: :quiet,
w: :watch_errors,
h: :help
]
@spec main(list(String.t())) :: no_return()
def main(args) do
{opts, _rest, invalid} = OptionParser.parse(args, strict: @switches, aliases: @aliases)
cond do
invalid != [] ->
IO.puts(:stderr, "Invalid options: #{inspect(invalid)}")
IO.puts(@help)
System.halt(1)
Keyword.get(opts, :help, false) ->
IO.puts(@help)
System.halt(0)
true ->
run_opts = %{
iterations: Keyword.get(opts, :iterations, 100),
base: Keyword.get(opts, :base, "main"),
seed: Keyword.get(opts, :seed),
dry_run: Keyword.get(opts, :dry_run, false),
parallel: Keyword.get(opts, :parallel),
mix: Keyword.get(opts, :mix, false),
failed: Keyword.get(opts, :failed, false),
print_full_log: Keyword.get(opts, :print_full_log, false),
quiet: Keyword.get(opts, :quiet, false),
watch_errors: Keyword.get(opts, :watch_errors, false)
}
case Flaky.run(run_opts) do
:ok -> System.halt(0)
{:error, _msg} -> System.halt(1)
end
end
end
end