diff --git a/.gitignore b/.gitignore index 0c6c638..a69cd41 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ # Ignore .fetch files in case you like to edit your project deps locally. /.fetch +/zig_compiler # If the VM crashes, it generates a dump, let's ignore it too. erl_crash.dump diff --git a/config/config.exs b/config/config.exs index b40de2b..fdb6cbd 100644 --- a/config/config.exs +++ b/config/config.exs @@ -66,6 +66,10 @@ config :compass_admin, CompassAdmin.Agents.GatewayAgent, input: ["\n"], execute: "pyinfra prod-nodes.py prod-nginx-deploy.py" +config :compass_admin, CompassAdmin.Agents.ProxyAgent, + input: [""], + execute: "pyinfra prod-nodes.py prod-proxy-restart.py" + config :compass_admin, CompassAdminWeb.ConfigurationLive, execute: "cd {config_dir} && git config user.name {username} && git config user.email {useremail} && git add {config_path} && git commit -m '{commit_message}' && git push" diff --git a/lib/compass_admin/agents/proxy_agent.ex b/lib/compass_admin/agents/proxy_agent.ex new file mode 100644 index 0000000..3ce59f7 --- /dev/null +++ b/lib/compass_admin/agents/proxy_agent.ex @@ -0,0 +1,61 @@ +defmodule CompassAdmin.Agents.ProxyAgent do + use GenServer + + alias CompassAdmin.User + alias CompassAdmin.Agents.DeployAgent + + @agent_svn "proxy_v1" + + def start_link(_) do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + def init(_) do + {:ok, DeployAgent.init(@agent_svn)} + end + + def execute(trigger_id) do + GenServer.cast(__MODULE__, {:deploy, trigger_id}) + end + + def get_state() do + GenServer.call(__MODULE__, :get_state) + end + + def update_deploy_state(deploy_state, last_deploy_id, last_deploy_result) do + GenServer.cast( + __MODULE__, + {:update_deploy_state, deploy_state, last_deploy_id, last_deploy_result} + ) + end + + def append_log(log) do + GenServer.cast(__MODULE__, {:append, log}) + end + + def handle_call(:get_state, _from, state) do + {:reply, state, state} + end + + def handle_cast({:update_deploy_state, deploy_state, last_deploy_id, last_deploy_result}, state) do + {:noreply, + DeployAgent.update_deploy_state( + state, + deploy_state, + last_deploy_id, + last_deploy_result + )} + end + + def handle_cast({:append, log}, state) do + {:noreply, DeployAgent.append_log(state, log)} + end + + def handle_cast({:deploy, trigger_id}, state) do + {:noreply, DeployAgent.deploy(__MODULE__, state, trigger_id, User.frontend_dev_role())} + end + + def handle_info(_msg, state) do + {:noreply, state} + end +end diff --git a/lib/compass_admin/application.ex b/lib/compass_admin/application.ex index 5be3890..166ae82 100644 --- a/lib/compass_admin/application.ex +++ b/lib/compass_admin/application.ex @@ -65,7 +65,8 @@ defmodule CompassAdmin.Application do # Deployment agents {CompassAdmin.Agents.GatewayAgent, []}, {CompassAdmin.Agents.BackendAgent, []}, - {CompassAdmin.Agents.FrontendAgent, []} + {CompassAdmin.Agents.FrontendAgent, []}, + {CompassAdmin.Agents.ProxyAgent, []}, ] |> Enum.reject(&is_nil/1) CompassAdmin.Plug.MetricsExporter.setup() diff --git a/lib/compass_admin_web/live/backoffice/layout.ex b/lib/compass_admin_web/live/backoffice/layout.ex index b604558..adabc62 100644 --- a/lib/compass_admin_web/live/backoffice/layout.ex +++ b/lib/compass_admin_web/live/backoffice/layout.ex @@ -91,6 +91,11 @@ defmodule CompassAdminWeb.Live.Backoffice.Layout do label: "Backend Applications", link: "/admin/deployments/backend", icon: ruby_icon() + }, + %{ + label: "Proxy Applications", + link: "/admin/deployments/proxy", + icon: proxy_icon() } ] }, diff --git a/lib/compass_admin_web/live/proxy_deployment_live.ex b/lib/compass_admin_web/live/proxy_deployment_live.ex new file mode 100644 index 0000000..ecf1392 --- /dev/null +++ b/lib/compass_admin_web/live/proxy_deployment_live.ex @@ -0,0 +1,88 @@ +defmodule CompassAdminWeb.ProxyDeploymentLive do + use CompassAdminWeb, :live_view + + alias CompassAdmin.User + alias CompassAdmin.Agents.ProxyAgent + + import CompassAdmin.Utils, only: [apm_call: 3] + + @impl true + def mount(_params, %{"current_user" => current_user}, socket) do + if connected?(socket), do: Process.send_after(self(), :refresh, 5000) + + state = apm_call(ProxyAgent, :get_state, []) + last_deploy_user = User.find(state.last_deploy_id, preloads: :login_binds) + last_trigger_user = User.find(state.last_trigger_id, preloads: :login_binds) + last_deployer = if last_deploy_user, do: List.first(last_deploy_user.login_binds) + last_trigger = if last_trigger_user, do: List.first(last_trigger_user.login_binds) + can_deploy = current_user.role_level >= User.frontend_dev_role() + + {:ok, + assign(socket, + title: "Proxy recent deployment logs", + agent_state: state, + can_deploy: can_deploy, + current_user: current_user, + last_trigger: last_trigger, + last_deployer: last_deployer + )} + end + + @impl true + def handle_params(_params, _uri, socket) do + case socket.assigns.live_action do + :index -> + {:noreply, assign(socket, action: :index)} + end + end + + @impl true + def handle_info(:refresh, socket) do + Process.send_after(self(), :refresh, 5000) + + state = apm_call(ProxyAgent, :get_state, []) + last_deploy_user = User.find(state.last_deploy_id, preloads: :login_binds) + last_trigger_user = User.find(state.last_trigger_id, preloads: :login_binds) + last_deployer = if last_deploy_user, do: List.first(last_deploy_user.login_binds) + last_trigger = if last_trigger_user, do: List.first(last_trigger_user.login_binds) + + {:noreply, + assign(socket, + agent_state: state, + last_trigger: last_trigger, + last_deployer: last_deployer + )} + end + + @impl true + def handle_event("deploy", _value, socket) do + apm_call(ProxyAgent, :execute, [socket.assigns.current_user.id]) + Process.sleep(1000) + state = apm_call(ProxyAgent, :get_state, []) + last_deploy_user = User.find(state.last_deploy_id, preloads: :login_binds) + last_trigger_user = User.find(state.last_trigger_id, preloads: :login_binds) + last_deployer = if last_deploy_user, do: List.first(last_deploy_user.login_binds) + last_trigger = if last_trigger_user, do: List.first(last_trigger_user.login_binds) + + {:noreply, + assign(socket, + agent_state: state, + last_trigger: last_trigger, + last_deployer: last_deployer + )} + end + + @impl true + def render(assigns) do + ~H""" + <.deployment_page + title={@title} + agent_state={@agent_state} + last_trigger={@last_trigger} + last_deployer={@last_deployer} + can_deploy={@can_deploy} + > + + """ + end +end diff --git a/lib/compass_admin_web/router.ex b/lib/compass_admin_web/router.ex index ac138e3..3251743 100644 --- a/lib/compass_admin_web/router.ex +++ b/lib/compass_admin_web/router.ex @@ -40,6 +40,7 @@ defmodule CompassAdminWeb.Router do live "/gitee/issues", GiteeIssuesLive, :index live "/gitee/issues/bulk", GiteeIssuesLive, :bulk + live "/deployments/proxy", ProxyDeploymentLive, :index live "/deployments/gateway", GatewayDeploymentLive, :index live "/deployments/backend", BackendDeploymentLive, :index live "/deployments/frontend", FrontendDeploymentLive, :index diff --git a/lib/compass_admin_web/views/icons_helpers.ex b/lib/compass_admin_web/views/icons_helpers.ex index 5e04b27..6558b3d 100644 --- a/lib/compass_admin_web/views/icons_helpers.ex +++ b/lib/compass_admin_web/views/icons_helpers.ex @@ -65,6 +65,19 @@ defmodule CompassAdminWeb.View.IconsHelpers do """ end + def proxy_icon() do + """ + + + + + + + + + """ + end + def ruby_icon() do """