diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 080fc99d..0d9287f7 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -71,7 +71,7 @@ jobs: rm -rf ./_build/${{ env.MIX_ENV }}/lib/supavisor UPGRADE_FROM=${{ env.RELEASE_FROM }} mix release supavisor - name: Create tarball - run: cd _build/prod/rel/ && tar -czvf ${{ env.NAME }}_$(date "+%s").tar.gz supavisor + run: cd _build/${{ env.MIX_ENV }} && mv supavisor-${{ env.RELEASE_TO }}.tar.gz "${{ env.NAME }}_$(date "+%s").tar.gz" - name: configure aws credentials - staging uses: aws-actions/configure-aws-credentials@v4 with: @@ -79,4 +79,4 @@ jobs: aws-region: "us-east-1" - name: Deploy to S3 shell: bash - run: aws s3 sync ./_build/prod/rel/ ${{ secrets.TARBALLS_PATH_STAGE }} --exclude '*' --include '*tar.gz' + run: aws s3 sync ./_build/${{ env.MIX_ENV }} ${{ secrets.TARBALLS_PATH_STAGE }} --exclude '*' --include '*tar.gz' diff --git a/config/config.exs b/config/config.exs index 5eb444bb..7255b2ec 100644 --- a/config/config.exs +++ b/config/config.exs @@ -9,7 +9,8 @@ import Config config :supavisor, ecto_repos: [Supavisor.Repo], - version: Mix.Project.config()[:version] + version: Mix.Project.config()[:version], + env: Mix.env() # Configures the endpoint config :supavisor, SupavisorWeb.Endpoint, diff --git a/lib/supavisor/hot_upgrade.ex b/lib/supavisor/hot_upgrade.ex new file mode 100644 index 00000000..713be55b --- /dev/null +++ b/lib/supavisor/hot_upgrade.ex @@ -0,0 +1,59 @@ +defmodule Supavisor.HotUpgrade do + @moduledoc false + + @type app :: atom + @type version_str :: String.t() + @type path_str :: String.t() + @type change :: :soft | {:advanced, [term]} + @type dep_mods :: [module] + @type appup_ver :: charlist | binary + @type instruction :: + {:add_module, module} + | {:delete_module, module} + | {:update, module, :supervisor | change} + | {:update, module, change, dep_mods} + | {:load_module, module} + | {:load_module, module, dep_mods} + | {:apply, {module, atom, [term]}} + | {:add_application, atom} + | {:remove_application, atom} + | {:restart_application, atom} + | :restart_new_emulator + | :restart_emulator + @type upgrade_instructions :: [{appup_ver, instruction}] + @type downgrade_instructions :: [{appup_ver, instruction}] + @type appup :: {appup_ver, upgrade_instructions, downgrade_instructions} + + @spec up(app(), version_str(), version_str(), [appup()], any()) :: [appup()] + def up(_app, _from_vsn, to_vsn, appup, _transform), + do: [{:apply, {Supavisor.HotUpgrade, :apply_runtime_config, [to_vsn]}} | appup] + + @spec down(app(), version_str(), version_str(), [appup()], any()) :: [appup()] + def down(_app, _from_vsn, to_vsn, appup, _transform), + do: [{:apply, {Supavisor.HotUpgrade, :apply_runtime_config, [to_vsn]}} | appup] + + @spec apply_runtime_config(version_str()) :: any() + def apply_runtime_config(vsn) do + path = + if System.get_env("DEBUG_LOAD_RUNTIME_CONFIG"), + do: "config/runtime.exs", + else: "releases/#{vsn}/runtime.exs" + + if File.exists?(path) do + IO.write("Loading runtime.exs from releases/#{vsn}") + + for {app, config} <- + Config.Reader.read!(path, env: Application.get_env(:supavisor, :env)) do + updated_config = + Config.Reader.merge( + [{app, Application.get_all_env(app)}], + [{app, config}] + ) + + Application.put_all_env(updated_config) + end + else + IO.write("No runtime.exs found in releases/#{vsn}") + end + end +end diff --git a/lib/supavisor/monitoring/prom_ex.ex b/lib/supavisor/monitoring/prom_ex.ex index afccdefa..72f92f9a 100644 --- a/lib/supavisor/monitoring/prom_ex.ex +++ b/lib/supavisor/monitoring/prom_ex.ex @@ -37,7 +37,7 @@ defmodule Supavisor.Monitoring.PromEx do |> :ets.select_delete([{{{:_, meta}, :_}, [], [true]}]) end - @spec set_metrics_tags() :: :ok + @spec set_metrics_tags() :: map() def set_metrics_tags() do [_, host] = node() |> Atom.to_string() |> String.split("@") @@ -53,6 +53,7 @@ defmodule Supavisor.Monitoring.PromEx do end Application.put_env(:supavisor, :metrics_tags, metrics_tags) + metrics_tags end @spec short_node_id() :: String.t() | nil @@ -68,9 +69,13 @@ defmodule Supavisor.Monitoring.PromEx do @spec get_metrics() :: String.t() def get_metrics() do - def_tags = - Application.fetch_env!(:supavisor, :metrics_tags) - |> Enum.map_join(",", fn {k, v} -> "#{k}=\"#{v}\"" end) + metrics_tags = + case Application.fetch_env(:supavisor, :metrics_tags) do + :error -> set_metrics_tags() + {:ok, tags} -> tags + end + + def_tags = Enum.map_join(metrics_tags, ",", fn {k, v} -> "#{k}=\"#{v}\"" end) metrics = PromEx.get_metrics(__MODULE__) diff --git a/lib/tasks/gen.appup.ex b/lib/tasks/gen.appup.ex index 005206ed..3476dfbb 100644 --- a/lib/tasks/gen.appup.ex +++ b/lib/tasks/gen.appup.ex @@ -32,7 +32,9 @@ defmodule Mix.Tasks.Supavisor.Gen.Appup do path_to = Path.join(lib_path, "supavisor-#{to_vsn}") appup_path = Path.join([path_to, "ebin", "supavisor.appup"]) - case Appup.make(:supavisor, from_vsn, to_vsn, path_from, path_to) do + transforms = [{Supavisor.HotUpgrade, []}] + + case Appup.make(:supavisor, from_vsn, to_vsn, path_from, path_to, transforms) do {:ok, appup} -> IO.puts("Writing appup to #{appup_path}")