defmodule Mix.Tasks.Mandrag do defmodule Deploy do use Mix.Task @shortdoc "Deploys an exrm release." def run(_) do case {initial_deploy?, rel_dir?(location)} do {true, _} -> prepare; build; start {false, hot?} -> build Code.ensure_loaded?(Ecto) && update_db hot? && hot_upgrade || cold_upgrade end end defp prepare, do: _prepare(location) defp build, do: _build(location) defp _prepare(:local) do ssh "mkdir -p #{name}/run" end defp _prepare(:remote) do ssh "git clone #{repo} #{name}" ssh "mkdir #{name}/priv/static" ssh "mkdir #{name}/run" end defp _build(:local) do Mix.Task.run "compile" Mix.Shell.IO.cmd "npm install" Mix.Shell.IO.cmd "node_modules/brunch/bin/brunch build --production" Mix.Task.run "phoenix.digest", [] Mix.Task.run "release", [] end defp _build(:remote) do ssh "cd #{name} && git pull" scp "config/prod.secret.exs", "#{name}/config/prod.secret.exs" ssh "cd #{name} && MIX_ENV=#{Mix.env} mix deps.get" ssh "cd #{name} && MIX_ENV=#{Mix.env} mix compile" ssh "cd #{name} && npm install" ssh "cd #{name} && node_modules/brunch/bin/brunch build --production" ssh "cd #{name} && MIX_ENV=#{Mix.env} mix phoenix.digest" ssh "cd #{name} && MIX_ENV=#{Mix.env} mix release" end defp start do case location do :local -> if Code.ensure_loaded?(Ecto) do Mix.Task.run "ecto.create", [] Mix.Task.run "ecto.migrate", [] Mix.Task.run "run", ["priv/repo/seeds.exs"] end scp "rel/#{name}/releases/#{version}/#{name}.tar.gz", "#{name}/run/#{name}.tar.gz" :remote -> if Code.ensure_loaded?(Ecto), do: ssh "cd #{name} && MIX_ENV=#{Mix.env} mix do ecto.create, ecto.migrate, run priv/repo/seeds.exs" ssh "cp #{name}/rel/#{name}/releases/#{version}/#{name}.tar.gz #{name}/run" end ssh "cd #{name}/run && tar xf #{name}.tar.gz && rm #{name}.tar.gz" _run("start") end defp update_db do case location do :local -> Mix.Task.run "ecto.migrate", [] :remote -> ssh "cd #{name} && MIX_ENV=#{Mix.env} mix ecto.migrate" end end defp hot_upgrade do case location do :local -> ssh "mkdir #{name}/releases/#{version}" scp "rel/#{name}/releases/#{version}/#{name}.tar.gz", "#{name}/releases/#{version}/#{name}.tar.gz" :remote -> ssh "mkdir #{name}/run/releases/#{version}" ssh "cp #{name}/rel/#{name}/releases/#{version}/#{name}.tar.gz #{name}/run/releases/#{version}/" scp "config/prod.secret.exs", "#{name}/config/prod.secret.exs" end _run("upgrade '#{version}'") end defp cold_upgrade do case location do :local -> scp "rel/#{name}/releases/#{version}/#{name}.tar.gz", "#{name}/run/#{name}.tar.gz" :remote -> ssh "cp #{name}/rel/#{name}/releases/#{version}/#{name}.tar.gz #{name}/run" end ssh "cd #{name}/run && tar xf #{name}.tar.gz && rm #{name}.tar.gz" _run("stop") _run("start") end defp _run(command), do: ssh("#{name}/run/bin/#{name} #{command}") defp initial_deploy?, do: ssh("ls #{name} &>/dev/null") != 0 defp rel_dir?(:remote), do: ssh("ls #{name}/rel/* %>/dev/null") == 0 defp rel_dir?(:local), do: Mix.Shell.IO.cmd("ls #{name}/rel/* %>/dev/null") == 0 # ssh helpers defp ssh_options, do: "-i#{key} -oStrictHostKeyChecking=no" defp ssh(command), do: Mix.Shell.IO.cmd "ssh #{user}@#{host} #{ssh_options} '#{command}'" defp scp(source, destination), do: Mix.Shell.IO.cmd "scp #{ssh_options} #{source} #{user}@#{host}:#{destination}" # config helpers defp location, do: Application.get_env(:mandrag, :build_location) defp user, do: Application.get_env(:mandrag, :user) defp host, do: Application.get_env(:mandrag, :host) defp key, do: Application.get_env(:mandrag, :key) defp name, do: Application.get_env(:mandrag, :name) defp version, do: Application.get_env(:mandrag, :version) defp repo, do: Application.get_env(:mandrag, :repo) end end