Skip to content

Commit 57c9069

Browse files
committed
Add --warnings-as-errors flag for non-zero exit code
1 parent fcfd2b9 commit 57c9069

File tree

10 files changed

+98
-26
lines changed

10 files changed

+98
-26
lines changed

lib/ex_doc/application.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ defmodule ExDoc.Application do
1717
match?("makeup_" <> _, Atom.to_string(app)),
1818
do: Application.ensure_all_started(app)
1919

20-
Supervisor.start_link([ExDoc.Refs], strategy: :one_for_one)
20+
Supervisor.start_link([ExDoc.Refs, ExDoc.WarningCounter], strategy: :one_for_one)
2121
end
2222
end

lib/ex_doc/cli.ex

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ defmodule ExDoc.CLI do
2626
package: :string,
2727
proglang: :string,
2828
source_ref: :string,
29-
version: :boolean
29+
version: :boolean,
30+
warnings_as_errors: :boolean
3031
]
3132
)
3233

@@ -35,6 +36,11 @@ defmodule ExDoc.CLI do
3536
else
3637
generate(args, opts, generator)
3738
end
39+
40+
if List.keymember?(opts, :warnings_as_errors, 0) and ExDoc.WarningCounter.count() > 0 do
41+
IO.warn("Doc generation failed due to warnings while using the --warnings-as-errors option")
42+
exit({:shutdown, ExDoc.WarningCounter.count()})
43+
end
3844
end
3945

4046
defp print_version do
@@ -140,27 +146,28 @@ defmodule ExDoc.CLI do
140146
ex_doc "Project" "1.0.0" "_build/dev/lib/project/ebin" -c "docs.exs"
141147
142148
Options:
143-
PROJECT Project name
144-
VERSION Version number
145-
BEAMS Path to compiled beam files
146-
-n, --canonical Indicate the preferred URL with rel="canonical" link element
147-
-c, --config Give configuration through a file instead of a command line.
148-
See "Custom config" section below for more information.
149-
-f, --formatter Docs formatter to use (html or epub), default: "html"
150-
-p, --homepage-url URL to link to for the site name
151-
--paths Prepends the given path to Erlang code path. The path might contain a glob
152-
pattern but in that case, remember to quote it: --paths "_build/dev/lib/*/ebin".
153-
This option can be given multiple times
154-
--language Identify the primary language of the documents, its value must be
155-
a valid [BCP 47](https://tools.ietf.org/html/bcp47) language tag, default: "en"
156-
-l, --logo Path to the image logo of the project (only PNG or JPEG accepted)
157-
The image size will be 64x64 and copied to the assets directory
158-
-m, --main The entry-point page in docs, default: "api-reference"
159-
--package Hex package name
160-
--source-ref Branch/commit/tag used for source link inference, default: "master"
161-
-u, --source-url URL to the source code
162-
-o, --output Path to output docs, default: "doc"
163-
-v, --version Print ExDoc version
149+
PROJECT Project name
150+
VERSION Version number
151+
BEAMS Path to compiled beam files
152+
-n, --canonical Indicate the preferred URL with rel="canonical" link element
153+
-c, --config Give configuration through a file instead of a command line.
154+
See "Custom config" section below for more information.
155+
-f, --formatter Docs formatter to use (html or epub), default: "html"
156+
-p, --homepage-url URL to link to for the site name
157+
--paths Prepends the given path to Erlang code path. The path might contain a glob
158+
pattern but in that case, remember to quote it: --paths "_build/dev/lib/*/ebin".
159+
This option can be given multiple times
160+
--language Identify the primary language of the documents, its value must be
161+
a valid [BCP 47](https://tools.ietf.org/html/bcp47) language tag, default: "en"
162+
-l, --logo Path to the image logo of the project (only PNG or JPEG accepted)
163+
The image size will be 64x64 and copied to the assets directory
164+
-m, --main The entry-point page in docs, default: "api-reference"
165+
--package Hex package name
166+
--source-ref Branch/commit/tag used for source link inference, default: "master"
167+
-u, --source-url URL to the source code
168+
-o, --output Path to output docs, default: "doc"
169+
-v, --version Print ExDoc version
170+
--warnings-as-errors Exit with non-zero status if doc generation has one or more warnings
164171
165172
## Custom config
166173

lib/ex_doc/config.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ defmodule ExDoc.Config do
4343
version: nil,
4444
authors: nil,
4545
skip_undefined_reference_warnings_on: [],
46-
package: nil
46+
package: nil,
47+
warnings_as_errors: false
4748

4849
@type t :: %__MODULE__{
4950
apps: [atom()],
@@ -78,6 +79,7 @@ defmodule ExDoc.Config do
7879
version: nil | String.t(),
7980
authors: nil | [String.t()],
8081
skip_undefined_reference_warnings_on: [String.t()],
81-
package: :atom | nil
82+
package: :atom | nil,
83+
warnings_as_errors: boolean()
8284
}
8385
end

lib/ex_doc/language.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ defmodule ExDoc.Language do
135135
def get(:erlang, _module), do: {:ok, ExDoc.Language.Erlang}
136136

137137
def get(language, module) when is_atom(language) and is_atom(module) do
138+
ExDoc.WarningCounter.increment()
139+
138140
IO.warn(
139141
"skipping module #{module}, reason: unsupported language (#{language})",
140142
[]

lib/ex_doc/markdown/earmark.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ defmodule ExDoc.Markdown.Earmark do
5252
defp print_messages(messages, options) do
5353
for {severity, line, message} <- messages do
5454
file = options[:file]
55+
ExDoc.WarningCounter.increment()
5556
IO.warn("#{inspect(__MODULE__)} (#{severity}) #{file}:#{line} #{message}", [])
5657
end
5758
end

lib/ex_doc/retriever.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ defmodule ExDoc.Retriever do
8181
docs
8282

8383
{:error, reason} ->
84+
ExDoc.WarningCounter.increment()
8485
IO.warn("skipping module #{inspect(module)}, reason: #{reason}", [])
8586
false
8687
end

lib/ex_doc/warning_counter.ex

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
defmodule ExDoc.WarningCounter do
2+
@moduledoc false
3+
4+
@name __MODULE__
5+
6+
use Agent
7+
8+
def start_link(_ \\ []) do
9+
Agent.start_link(fn -> 0 end, name: @name)
10+
end
11+
12+
def count do
13+
Agent.get(__MODULE__, & &1)
14+
end
15+
16+
def increment do
17+
Agent.update(__MODULE__, &(&1 + 1))
18+
end
19+
end

lib/mix/tasks/docs.ex

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ defmodule Mix.Tasks.Docs do
2121
* `--language` - Specifies the language to annotate the
2222
EPUB output in valid [BCP 47](https://tools.ietf.org/html/bcp47)
2323
24+
* `--warnings-as-errors` - Exits with non-zero exit code if any warnings are found
25+
2426
The command line options have higher precedence than the options
2527
specified in your `mix.exs` file below.
2628
@@ -299,7 +301,8 @@ defmodule Mix.Tasks.Docs do
299301
canonical: :string,
300302
formatter: :keep,
301303
language: :string,
302-
output: :string
304+
output: :string,
305+
warnings_as_errors: :boolean
303306
]
304307

305308
@aliases [n: :canonical, f: :formatter, o: :output]
@@ -349,6 +352,16 @@ defmodule Mix.Tasks.Docs do
349352
for formatter <- get_formatters(options) do
350353
index = generator.(project, version, Keyword.put(options, :formatter, formatter))
351354
Mix.shell().info([:green, "View #{inspect(formatter)} docs at #{inspect(index)}"])
355+
356+
if List.keymember?(options, :warnings_as_errors, 0) and ExDoc.WarningCounter.count() > 0 do
357+
Mix.shell().info([
358+
:red,
359+
"Doc generation failed due to warnings while using the --warnings-as-errors option"
360+
])
361+
362+
exit({:shutdown, ExDoc.WarningCounter.count()})
363+
end
364+
352365
index
353366
end
354367
end

test/ex_doc/cli_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ defmodule ExDoc.CLITest do
2323
end) == "ExDoc v#{ExDoc.version()}\n"
2424
end
2525

26+
describe "--warnings-as-errors" do
27+
test "exits with 0 with no warnings" do
28+
assert {"ExDoc", "1.2.3", [_, _, warnings_as_errors: true]} =
29+
run(["ExDoc", "1.2.3", @ebin, "--warnings-as-errors"])
30+
end
31+
32+
test "exits with 1 with warnings" do
33+
fun = fn ->
34+
assert capture_io(fn ->
35+
run(["ExDoc", "1.2.3", @ebin, "--warnings-as-errors"])
36+
end) =~
37+
"Doc generation failed due to warnings while using the --warnings-as-errors option\n"
38+
end
39+
40+
assert catch_exit(fun.()) == {:shutdown, 1}
41+
end
42+
end
43+
2644
test "too many arguments" do
2745
fun = fn ->
2846
run(["ExDoc", "1.2.3", "/", "kaboom"])

test/mix/tasks/docs_test.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,13 @@ defmodule Mix.Tasks.DocsTest do
181181
] = run([], app: :umbrella, apps_path: "apps/", docs: [ignore_apps: [:foo]])
182182
end)
183183
end
184+
185+
test "accepts warnings_as_errors in :warnings_as_errors" do
186+
assert [
187+
{"ex_doc", "dev",
188+
[formatter: "html", deps: _, apps: _, source_beam: _, warnings_as_errors: true]},
189+
{"ex_doc", "dev",
190+
[formatter: "epub", deps: _, apps: _, source_beam: _, warnings_as_errors: true]}
191+
] = run([], app: :ex_doc, docs: [warnings_as_errors: true])
192+
end
184193
end

0 commit comments

Comments
 (0)