Skip to content

Commit

Permalink
chore: workflow for building soft upgrade tarball (#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
abc3 authored Mar 7, 2024
1 parent 8722b7f commit c34e609
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 18 deletions.
46 changes: 39 additions & 7 deletions .github/workflows/stage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Publish upgrade artifacts to staging
on:
push:
branches:
- main
- release_stage
env:
INCLUDE_ERTS: true
MIX_ENV: prod
Expand All @@ -16,7 +16,14 @@ jobs:
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Set upgrade variables
run: |
elixir ./deploy/upgrade/handler.exs all_keys ./deploy/upgrade/staging.config
echo "RELEASE_FROM=$(elixir ./deploy/upgrade/handler.exs upgrade_from ./deploy/upgrade/staging.config)" >> $GITHUB_ENV
echo "RELEASE_TO=$(elixir ./deploy/upgrade/handler.exs upgrade_to ./deploy/upgrade/staging.config)" >> $GITHUB_ENV
echo "NAME=$(elixir ./deploy/upgrade/handler.exs name ./deploy/upgrade/staging.config)" >> $GITHUB_ENV
- name: Setup Elixir
run: |
. ~/.asdf/asdf.sh
Expand All @@ -26,7 +33,27 @@ jobs:
- name: Set up Rust
uses: ATiltedTree/setup-rust@v1
with:
rust-version: stable
rust-version: stable
- name: Get git tags
run: git fetch --tags origin
- name: Checkout RELEASE_FROM
run: git checkout v${{ env.RELEASE_FROM }}
- name: Cache Mix
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
restore-keys: |
${{ runner.os }}-mix-
- name: Install dependencies
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get
- name: Make old release
run: mix release supavisor
- name: Checkout RELEASE_TO
run: git checkout v${{ env.RELEASE_TO }}
- name: Cache Mix
uses: actions/cache@v3
with:
Expand All @@ -39,15 +66,20 @@ jobs:
mix local.hex --force
mix local.rebar --force
mix deps.get
- name: Make release
run: mix release supavisor
- name: Clean up old release
run: |
rm -rf ./_build/${{ env.MIX_ENV }}/lib/supavisor
rm ./_build/${{ env.MIX_ENV }}/rel/supavisor/releases/COOKIE
rm ./_build/${{ env.MIX_ENV }}/supavisor-${{ env.RELEASE_FROM }}.tar.gz
- name: Make upgrade release
run: RELEASE_COOKIE=${{ secrets.RELEASE_COOKIE_STAGE }} UPGRADE_FROM=${{ env.RELEASE_FROM }} mix release supavisor
- name: Create tarball
run: cd _build/prod/rel/ && tar -czvf ${{ secrets.TARBALL_REGIONS_STAGE }}_supavisor_v$(cat ../../../VERSION)_$(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:
role-to-assume: ${{ secrets.DEV_AWS_ROLE }}
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'
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.40
1.1.41
3 changes: 2 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 23 additions & 0 deletions deploy/upgrade/handler.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Handler do
def main([key, config]) do
{:ok, [config]} = :file.consult(config)

case key do
"all_keys" ->
IO.write(inspect(config, pretty: true))
"name" ->
regions = Enum.join(config[:regions], "&")

IO.write(
"supavisor_#{config[:type]}_#{regions}_#{config[:upgrade_from]}_#{config[:upgrade_to]}"
)

key ->
IO.write(config[String.to_atom(key)])
end

end
end


Handler.main(System.argv())
9 changes: 9 additions & 0 deletions deploy/upgrade/prod.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{upgrade_from, "x.x.x"},
{upgrade_to, "x.x.x"},
% list() | [:all]
{regions, ["ap-southeast-1"]},
% :soft | :hard
{type, soft}
].
% supavisor_soft_all-1_1.1.13_1.1.39
9 changes: 9 additions & 0 deletions deploy/upgrade/staging.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{upgrade_from, "x.x.x"},
{upgrade_to, "x.x.x"},
% list() | [:all]
{regions, ["ap-southeast-1"]},
% :soft | :hard
{type, soft}
].
% supavisor_soft_all-1_1.1.13_1.1.39
7 changes: 6 additions & 1 deletion lib/supavisor/client_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ defmodule Supavisor.ClientHandler do
@impl true
def handle_event(:info, {_proto, _, <<"GET", _::binary>>}, :exchange, data) do
Logger.debug("ClientHandler: Client is trying to request HTTP")
HH.sock_send(data.sock, "HTTP/1.1 204 OK\r\n\r\n")

HH.sock_send(
data.sock,
"HTTP/1.1 204 OK\r\nx-app-version: #{Application.spec(:supavisor, :vsn)}\r\n\r\n"
)

{:stop, {:shutdown, :http_request}}
end

Expand Down
59 changes: 59 additions & 0 deletions lib/supavisor/hot_upgrade.ex
Original file line number Diff line number Diff line change
@@ -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, [from_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
13 changes: 9 additions & 4 deletions lib/supavisor/monitoring/prom_ex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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("@")

Expand All @@ -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
Expand All @@ -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__)
Expand Down
4 changes: 3 additions & 1 deletion lib/tasks/gen.appup.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}")

Expand Down
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ defmodule Supavisor.MixProject do
[
supavisor: [
steps: [:assemble, &upgrade/1, :tar],
include_erts: System.get_env("INCLUDE_ERTS", "true") == "true"
include_erts: System.get_env("INCLUDE_ERTS", "true") == "true",
cookie: System.get_env("RELEASE_COOKIE", Base.url_encode64(:crypto.strong_rand_bytes(30)))
],
supavisor_bin: [
steps: [:assemble, &Burrito.wrap/1],
Expand Down Expand Up @@ -118,7 +119,7 @@ defmodule Supavisor.MixProject do
defp upgrade(release) do
from = System.get_env("UPGRADE_FROM")

if from do
if from && from != "" do
vsn = release.version
path = Path.join([release.path, "releases", "supavisor-#{vsn}.rel"])
rel_content = File.read!(Path.join(release.version_path, "supavisor.rel"))
Expand Down
4 changes: 3 additions & 1 deletion test/integration/proxy_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ defmodule Supavisor.Integration.ProxyTest do
assert :httpc.request(
"http://localhost:#{Application.get_env(:supavisor, :proxy_port_transaction)}"
) ==
{:ok, {{'HTTP/1.1', 204, 'OK'}, [], []}}
{:ok,
{{'HTTP/1.1', 204, 'OK'}, [{'x-app-version', Application.spec(:supavisor, :vsn)}],
[]}}
end

test "checks that client_handler is idle and db_pid is nil for transaction mode" do
Expand Down

0 comments on commit c34e609

Please sign in to comment.