Skip to content

Commit 4f111f6

Browse files
authored
Allow --output argument in "mix sentry.package_source_code" (#691)
1 parent 1ac4b93 commit 4f111f6

File tree

5 files changed

+98
-9
lines changed

5 files changed

+98
-9
lines changed

lib/mix/tasks/sentry.package_source_code.ex

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,34 @@ defmodule Mix.Tasks.Sentry.PackageSourceCode do
4343
> source-context-related options in compile-time config files (like `config/config.exs`
4444
> or `config/prod.exs`).
4545
46+
> #### Building with Nix {: .tip}
47+
>
48+
> If you build your application using nixpkgs' `mixRelease`,
49+
> `mix sentry.package_source_code` will fail, because Sentry's source is read-only.
50+
>
51+
> To fix this, you can use the `--output` option to write the map file to a writable location,
52+
> then copy it to Sentry's `priv` in the final OTP release.
53+
>
54+
> Example:
55+
>
56+
> ```nix
57+
> mixRelease {
58+
> preBuild = ''
59+
> mix sentry.package_source_code --output sentry.map
60+
> '';
61+
>
62+
> postInstall = ''
63+
> sentryPrivDir="$(find $out/lib -maxdepth 1 -name "sentry-*")/priv"
64+
> mkdir "$sentryPrivDir"
65+
> cp -a sentry.map "$sentryPrivDir"
66+
> '';
67+
> }
68+
> ```
69+
4670
## Options
4771
4872
* `--debug` - print more information about collecting and encoding source code
73+
* `--output path` - write file to the given path. Example: `path/to/sentry.map`
4974
5075
"""
5176

@@ -59,7 +84,10 @@ defmodule Mix.Tasks.Sentry.PackageSourceCode do
5984
@bytes_in_mb 1024 * 1024
6085
@bytes_in_gb 1024 * 1024 * 1024
6186

62-
@switches [debug: :boolean]
87+
@switches [
88+
debug: :boolean,
89+
output: :string
90+
]
6391

6492
@impl true
6593
def run(args) do
@@ -83,7 +111,7 @@ defmodule Mix.Tasks.Sentry.PackageSourceCode do
83111
{elapsed, contents} = :timer.tc(fn -> Sources.encode_source_code_map(source_map) end)
84112
log_debug(opts, "Encoded source code map in #{format_time(elapsed)}")
85113

86-
output_path = Sources.path_of_packaged_source_code()
114+
output_path = Keyword.get_lazy(opts, :output, &Sources.path_of_packaged_source_code/0)
87115
File.mkdir_p!(Path.dirname(output_path))
88116
File.write!(output_path, contents)
89117

lib/sentry/config.ex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ defmodule Sentry.Config do
6161
The name of the server running the application. Not used by default.
6262
"""
6363
],
64+
source_code_map_path: [
65+
type: {:custom, __MODULE__, :__validate_path__, []},
66+
default: nil,
67+
type_doc: "`t:Path.t/0` or `nil`",
68+
doc: """
69+
The path to the map file when mix task `sentry.package_source_code` was invoked with
70+
`--output path/to/file.map`
71+
"""
72+
],
6473
sample_rate: [
6574
type: {:custom, __MODULE__, :__validate_sample_rate__, []},
6675
default: 1.0,
@@ -399,6 +408,9 @@ defmodule Sentry.Config do
399408
@spec server_name() :: String.t() | nil
400409
def server_name, do: get(:server_name)
401410

411+
@spec source_code_map_path() :: Path.t() | nil
412+
def source_code_map_path, do: get(:source_code_map_path)
413+
402414
@spec filter() :: module()
403415
def filter, do: fetch!(:filter)
404416

@@ -528,6 +540,16 @@ defmodule Sentry.Config do
528540
:persistent_term.get({:sentry_config, key}, nil)
529541
end
530542

543+
def __validate_path__(nil), do: {:ok, nil}
544+
545+
def __validate_path__(path) when is_binary(path) do
546+
if File.exists?(path) do
547+
{:ok, path}
548+
else
549+
{:error, "path does not exist"}
550+
end
551+
end
552+
531553
def __validate_sample_rate__(float) do
532554
if is_float(float) and float >= 0.0 and float <= 1.0 do
533555
{:ok, float}

lib/sentry/sources.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ defmodule Sentry.Sources do
1414

1515
# Default argument is here for testing.
1616
@spec load_source_code_map_if_present(Path.t()) :: {:loaded, source_map()} | {:error, term()}
17-
def load_source_code_map_if_present(path \\ path_of_packaged_source_code()) do
17+
def load_source_code_map_if_present(
18+
path \\ Config.source_code_map_path() || path_of_packaged_source_code()
19+
) do
1820
path = Path.relative_to_cwd(path)
1921

2022
with {:ok, contents} <- File.read(path),

test/mix/sentry.package_source_code_test.exs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,24 @@ defmodule Mix.Tasks.Sentry.PackageSourceCodeTest do
2020

2121
assert :ok = Mix.Task.rerun("sentry.package_source_code")
2222

23-
assert_receive {:mix_shell, :info, ["Wrote " <> _ = message]}
24-
assert message =~ expected_path
23+
validate_map_file!(expected_path)
24+
end
2525

26-
assert {:ok, contents} = File.read(expected_path)
26+
@tag :tmp_dir
27+
test "packages source code into custom path", %{tmp_dir: tmp_dir} do
28+
put_test_config(
29+
root_source_code_paths: [File.cwd!()],
30+
enable_source_code_context: true
31+
)
2732

28-
assert %{"version" => 1, "files_map" => source_map} =
29-
:erlang.binary_to_term(contents, [:safe])
33+
expected_path =
34+
[tmp_dir, "sentry.map"]
35+
|> Path.join()
36+
|> Path.relative_to_cwd()
3037

31-
assert Map.has_key?(source_map, "lib/mix/tasks/sentry.package_source_code.ex")
38+
assert :ok = Mix.Task.rerun("sentry.package_source_code", ["--output", expected_path])
39+
40+
validate_map_file!(expected_path)
3241
end
3342

3443
test "supports the --debug option" do
@@ -51,4 +60,16 @@ defmodule Mix.Tasks.Sentry.PackageSourceCodeTest do
5160
{:mix_shell, :info, ["Wrote " <> _]}
5261
]} = Process.info(self(), :messages)
5362
end
63+
64+
defp validate_map_file!(path) do
65+
assert_receive {:mix_shell, :info, ["Wrote " <> _ = message]}
66+
assert message =~ path
67+
68+
assert {:ok, contents} = File.read(path)
69+
70+
assert %{"version" => 1, "files_map" => source_map} =
71+
:erlang.binary_to_term(contents, [:safe])
72+
73+
assert Map.has_key?(source_map, "lib/mix/tasks/sentry.package_source_code.ex")
74+
end
5475
end

test/sentry/config_test.exs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ defmodule Sentry.ConfigTest do
5050
end
5151
end
5252

53+
@tag :tmp_dir
54+
test ":source_code_map_path from option", %{tmp_dir: tmp_dir} do
55+
source_code_map_path = Path.join([tmp_dir, "test.map"])
56+
57+
assert Config.validate!(source_code_map_path: nil)[:source_code_map_path] == nil
58+
59+
assert_raise ArgumentError, ~r/path does not exist/, fn ->
60+
assert Config.validate!(source_code_map_path: source_code_map_path)
61+
end
62+
63+
File.touch!(source_code_map_path)
64+
65+
assert Config.validate!(source_code_map_path: source_code_map_path)[:source_code_map_path] ==
66+
source_code_map_path
67+
end
68+
5369
test ":release from option" do
5470
assert Config.validate!(release: "1.0.0")[:release] == "1.0.0"
5571
end

0 commit comments

Comments
 (0)