diff --git a/README.md b/README.md index 4afa2eb..93272d1 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,24 @@ Or you can pass it through when creating a client instance: knock_client = MyApp.Knock.client(api_key: "sk_12345") ``` +To use a branch, set the `branch` option in your configuration or client instance: + +```elixir +config :my_app, MyApp.Knock, + api_key: "sk_12345" + branch: "my-feature-branch" + +# OR + +knock_client = MyApp.Knock.client(api_key: "sk_12345", branch: "my-feature-branch") +``` + +Alternatively, you can set it as an environment variable: + +```bash +KNOCK_BRANCH="my-feature-branch" +``` + ## Usage ### Identifying users diff --git a/lib/knock.ex b/lib/knock.ex index 0d12535..aa734c1 100644 --- a/lib/knock.ex +++ b/lib/knock.ex @@ -49,13 +49,28 @@ defmodule Knock do json_client: JSX ``` - You can read more about the availble adapters in the [Tesla documentation](https://hexdocs.pm/tesla/readme.html#adapters) + You can read more about the available adapters in the [Tesla documentation](https://hexdocs.pm/tesla/readme.html#adapters) + + To use a branch, set the `branch` option in your configuration or client instance. + + ```elixir + # config/runtime.exs + + config :my_app, MyApp.KnockClient, + api_key: "sk_12345", + branch: "my-feature-branch" + + # OR + + knock_client = MyApp.Knock.client(api_key: "sk_12345", branch: "my-feature-branch") + ``` """ defmacro __using__(opts) do quote do @app_name Keyword.fetch!(unquote(opts), :otp_app) @api_key_env_var "KNOCK_API_KEY" + @branch_env_var "KNOCK_BRANCH" alias Knock.Client @@ -72,6 +87,7 @@ defmodule Knock do defp fetch_options(overrides) do Application.get_env(@app_name, __MODULE__, []) |> maybe_resolve_api_key() + |> maybe_resolve_branch() |> Keyword.merge(overrides) end @@ -82,6 +98,14 @@ defmodule Knock do _ -> Keyword.put(opts, :api_key, System.get_env(@api_key_env_var)) end end + + defp maybe_resolve_branch(opts) do + case Keyword.get(opts, :branch) do + branch when is_binary(branch) -> opts + {:system, var_name} -> Keyword.put(opts, :branch, System.get_env(var_name)) + _ -> Keyword.put(opts, :branch, System.get_env(@branch_env_var)) + end + end end end diff --git a/lib/knock/api.ex b/lib/knock/api.ex index f945cac..a187553 100644 --- a/lib/knock/api.ex +++ b/lib/knock/api.ex @@ -91,7 +91,9 @@ defmodule Knock.Api do [ {"Authorization", "Bearer " <> config.api_key}, {"User-Agent", "knocklabs/knock-elixir@#{library_version()}"} - ] ++ maybe_idempotency_key_header(Map.new(opts))} + ] ++ + maybe_idempotency_key_header(Map.new(opts)) ++ + maybe_branch_header(config)} ] Tesla.client(middleware, config.adapter) @@ -101,4 +103,9 @@ defmodule Knock.Api do do: [{"Idempotency-Key", to_string(key)}] defp maybe_idempotency_key_header(_), do: [] + + defp maybe_branch_header(%{branch: branch}) when not is_nil(branch), + do: [{"X-Knock-Branch", to_string(branch)}] + + defp maybe_branch_header(_), do: [] end diff --git a/lib/knock/client.ex b/lib/knock/client.ex index e9f5dbb..e7994f4 100644 --- a/lib/knock/client.ex +++ b/lib/knock/client.ex @@ -7,12 +7,16 @@ defmodule Knock.Client do ```elixir # Setup a client instance directly client = Knock.Client.new(api_key: "sk_test_12345") + + # With optional branch + client = Knock.Client.new(api_key: "sk_test_12345", branch: "my-feature-branch") ``` """ @enforce_keys [:api_key] defstruct host: "https://api.knock.app", api_key: nil, + branch: nil, adapter: Tesla.Adapter.Hackney, json_client: Jason @@ -22,6 +26,7 @@ defmodule Knock.Client do @type t :: %__MODULE__{ host: String.t(), api_key: String.t(), + branch: String.t() | nil, adapter: atom(), json_client: atom() } @@ -38,7 +43,7 @@ defmodule Knock.Client do opts = opts - |> Keyword.take([:host, :api_key, :adapter, :json_client]) + |> Keyword.take([:host, :api_key, :branch, :adapter, :json_client]) |> Map.new() |> maybe_set_adapter_default() diff --git a/test/knock_test.exs b/test/knock_test.exs index 2ad7c41..900fd2e 100644 --- a/test/knock_test.exs +++ b/test/knock_test.exs @@ -14,6 +14,14 @@ defmodule KnockTest do assert knock.adapter == Tesla.Adapter.Hackney assert knock.json_client == Jason assert knock.host == "https://api.knock.app" + assert knock.branch == nil + end + + test "it allows configuring a branch" do + knock = TestClient.client(api_key: "sk_test_12345", branch: "my-feature-branch") + + assert knock.api_key == "sk_test_12345" + assert knock.branch == "my-feature-branch" end test "it will default to reading the api key from env vars" do @@ -24,7 +32,18 @@ defmodule KnockTest do assert knock.api_key == "sk_test_12345" end - test "it can read from application config" do + test "it will default to reading the branch from env vars" do + System.put_env("KNOCK_API_KEY", "sk_test_12345") + System.put_env("KNOCK_BRANCH", "test-branch") + + knock = TestClient.client() + + assert knock.branch == "test-branch" + + System.delete_env("KNOCK_BRANCH") + end + + test "it can read the api key from application config" do Application.put_env(:knock, KnockTest.TestClient, api_key: "sk_test_12345", foo: "bar" @@ -35,6 +54,20 @@ defmodule KnockTest do assert knock.api_key == "sk_test_12345" end + test "it can read the branch from application config" do + Application.put_env(:knock, KnockTest.TestClient, + api_key: "sk_test_12345", + branch: "config-branch" + ) + + knock = TestClient.client() + + assert knock.api_key == "sk_test_12345" + assert knock.branch == "config-branch" + + Application.delete_env(:knock, KnockTest.TestClient) + end + test "if set, will use the Tesla default adapter if one is not provided" do Application.put_env(:tesla, :adapter, Tesla.Adapter.Hackney)