Skip to content

Commit fe7a713

Browse files
committed
Document using .erlang.crypt with ExDoc
Closes elixir-lang#1928. - Update documentation - Update test helper so that debug info options are forwarded to the compiler - Add basic tests - Update changelog - Use "CI" environment variable to skip the encrypted debug info test
1 parent d571628 commit fe7a713

File tree

6 files changed

+81
-6
lines changed

6 files changed

+81
-6
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
runs-on: ubuntu-20.04
1313
env:
1414
MIX_ENV: test
15+
CI: true
1516
strategy:
1617
fail-fast: false
1718
matrix:

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Improve warning when referencing type from a private module
77
* Rename "Search HexDocs package" modal to "Go to package docs". Support built-in Erlang/OTP
88
apps.
9+
* Document how to use `.erlang.crypt` with ExDoc
910

1011
* Bug fixes
1112
* Switch anchor `title` to `aria-label`

lib/mix/tasks/docs.ex

+8
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@ defmodule Mix.Tasks.Docs do
200200
where path is either an relative path from the cwd, or an absolute path. The function
201201
must return the full URI as it should be placed in the documentation.
202202
203+
## Encrypted debug info
204+
205+
If a module is compiled with [encrypted debug info](`:compile.file/2`), ExDoc will not be able to
206+
extract its documentation without preparation. ExDoc supports using `.erlang.crypt` to decrypt
207+
debug information. Consult the
208+
[`.erlang.crypt` section in the `:beam_lib` documentation](`m::beam_lib#module-erlang-crypt`)
209+
for more information.
210+
203211
## Groups
204212
205213
ExDoc content can be organized in groups. This is done via the `:groups_for_extras`

test/ex_doc/retriever/erlang_test.exs

+55
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,61 @@ defmodule ExDoc.Retriever.ErlangTest do
354354
|> Erlang.autolink_spec(current_module: :mod, current_kfa: {:type, :type, 0}) ==
355355
"type() :: #a{a :: <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:pos_integer/0\">pos_integer</a>(), b :: <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:non_neg_integer/0\">non_neg_integer</a>(), c :: <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:atom/0\">atom</a>(), d :: <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:term/0\">term</a>(), e :: <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:term/0\">term</a>()}."
356356
end
357+
358+
@tag :ci
359+
test "modules with encrypted debug info", c do
360+
File.cp!("test/fixtures/.erlang.crypt", ".erlang.crypt")
361+
362+
erlc(
363+
c,
364+
:debug_info_mod,
365+
~S"""
366+
-module(debug_info_mod).
367+
-moduledoc("mod docs.").
368+
-export([function1/0]).
369+
-export_type([foo/0]).
370+
371+
-doc("foo/0 docs.").
372+
-type foo() :: atom().
373+
374+
-doc("function1/0 docs.").
375+
-spec function1() -> atom().
376+
function1() -> ok.
377+
""",
378+
debug_info_key: ~c"SECRET"
379+
)
380+
381+
{[mod], []} = Retriever.docs_from_modules([:debug_info_mod], %ExDoc.Config{})
382+
383+
assert %ExDoc.ModuleNode{
384+
moduledoc_file: moduledoc_file,
385+
docs: [function1],
386+
id: "debug_info_mod",
387+
module: :debug_info_mod,
388+
title: "debug_info_mod",
389+
typespecs: [foo]
390+
} = mod
391+
392+
assert DocAST.to_string(mod.doc) =~ "mod docs."
393+
assert DocAST.to_string(function1.doc) =~ "function1/0 docs."
394+
assert DocAST.to_string(foo.doc) =~ "foo/0 docs."
395+
assert moduledoc_file =~ "debug_info_mod.erl"
396+
397+
erlc(
398+
c,
399+
:debug_info_mod2,
400+
~S"""
401+
-module(debug_info_mod2).
402+
-moduledoc("mod docs.").
403+
""",
404+
debug_info_key: {:des3_cbc, ~c"PASSWORD"}
405+
)
406+
407+
assert {[%ExDoc.ModuleNode{module: :debug_info_mod2}], []} =
408+
Retriever.docs_from_modules([:debug_info_mod2], %ExDoc.Config{})
409+
410+
File.rm!(".erlang.crypt")
411+
end
357412
end
358413

359414
describe "docs_from_modules/2 edoc" do

test/fixtures/.erlang.crypt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[{debug_info, des3_cbc, debug_info_mod, "SECRET"},
2+
{debug_info, des3_cbc, [], "PASSWORD"}].

test/test_helper.exs

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
otp_eep48? = Code.ensure_loaded?(:edoc_doclet_chunks)
22
otp_eep59? = Code.ensure_loaded?(:beam_doc)
3+
ci? = System.get_env("CI") == "true"
34

45
exclude = [
56
otp_eep48: not otp_eep48?,
67
otp_eep59: not otp_eep59?,
7-
otp_has_docs: not match?({:docs_v1, _, _, _, _, _, _}, Code.fetch_docs(:array))
8+
otp_has_docs: not match?({:docs_v1, _, _, _, _, _, _}, Code.fetch_docs(:array)),
9+
ci: not ci?
810
]
911

1012
ExUnit.start(exclude: Enum.filter(exclude, &elem(&1, 1)))
@@ -58,14 +60,20 @@ defmodule TestHelper do
5860

5961
beam_docs = docstrings(docs, context)
6062

63+
# not to be confused with the regular :debug_info opt
64+
debug_info_opts =
65+
Enum.filter(opts, fn
66+
{:debug_info, _debug_info} -> true
67+
{:debug_info_key, _debug_info_key} -> true
68+
:encrypt_debug_info -> true
69+
_ -> false
70+
end)
71+
6172
{:ok, module} =
6273
:compile.file(
6374
String.to_charlist(src_path),
64-
[
65-
:return_errors,
66-
:debug_info,
67-
outdir: String.to_charlist(ebin_dir)
68-
] ++ beam_docs
75+
[:return_errors, :debug_info, outdir: String.to_charlist(ebin_dir)] ++
76+
beam_docs ++ debug_info_opts
6977
)
7078

7179
true = Code.prepend_path(ebin_dir)

0 commit comments

Comments
 (0)