Start refactoring update handler. [WIP]
parent
0413855d74
commit
40d1d9ecde
|
@ -5,11 +5,11 @@ defmodule Farmbot.CeleryScript.AST.Node.CheckUpdates do
|
|||
|
||||
def execute(%{package: :farmbot_os}, _, env) do
|
||||
env = mutate_env(env)
|
||||
case Farmbot.System.Updates.check_updates(true) do
|
||||
:ok -> {:ok, env}
|
||||
:no_update -> {:ok, env}
|
||||
_ -> {:error, "Failed to check updates", env}
|
||||
end
|
||||
# case Farmbot.System.Updates.check_updates(true) do
|
||||
# :ok -> {:ok, env}
|
||||
# :no_update -> {:ok, env}
|
||||
# _ -> {:error, "Failed to check updates", env}
|
||||
# end
|
||||
end
|
||||
|
||||
def execute(%{package: :arduino_firmware}, _, env) do
|
||||
|
|
|
@ -21,7 +21,6 @@ defmodule Farmbot.System.Debug do
|
|||
]
|
||||
children = [
|
||||
Plug.Adapters.Cowboy.child_spec(:http, DebugRouter, [], options),
|
||||
worker(Farmbot.System.Updates.SlackUpdater, []),
|
||||
]
|
||||
|
||||
opts = [strategy: :one_for_one]
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
defmodule Farmbot.System.Updates.SlackUpdater do
|
||||
@moduledoc """
|
||||
Development module for auto flashing fw updates.
|
||||
"""
|
||||
|
||||
@token System.get_env("SLACK_TOKEN")
|
||||
@target Farmbot.Project.target()
|
||||
@data_path Application.get_env(:farmbot, :data_path)
|
||||
|
||||
use Farmbot.Logger
|
||||
use GenServer
|
||||
|
||||
defmodule RTMSocket do
|
||||
@moduledoc false
|
||||
def start_link(url, cb) do
|
||||
pid = spawn(__MODULE__, :socket_init, [url, cb])
|
||||
{:ok, pid}
|
||||
end
|
||||
|
||||
def socket_init("wss://" <> url, cb) do
|
||||
[domain | rest] = String.split(url, "/")
|
||||
|
||||
domain
|
||||
|> Socket.Web.connect!(secure: true, path: "/" <> Enum.join(rest, "/"))
|
||||
|> socket_loop(cb)
|
||||
end
|
||||
|
||||
def socket_init("ws://" <> url, cb) do
|
||||
[domain | rest] = String.split(url, "/")
|
||||
|
||||
domain
|
||||
|> Socket.Web.connect!(secure: false, path: "/" <> Enum.join(rest, "/"))
|
||||
|> socket_loop(cb)
|
||||
end
|
||||
|
||||
defp socket_loop(socket, cb) do
|
||||
case socket |> Socket.Web.recv!() do
|
||||
{:text, data} -> data |> Poison.decode!() |> handle_data(socket, cb)
|
||||
{:ping, _} -> Socket.Web.send!(socket, {:pong, ""})
|
||||
end
|
||||
|
||||
receive do
|
||||
{:stop, reason} ->
|
||||
term_msg =
|
||||
%{
|
||||
type: "message",
|
||||
id: 2,
|
||||
channel: "C58DCU4A3",
|
||||
text: ":farmbot-genesis: #{node()} Disconnected (#{inspect(reason)})"
|
||||
}
|
||||
|> Poison.encode!()
|
||||
|
||||
Socket.Web.send!(socket, {:text, term_msg})
|
||||
Socket.Web.close(socket)
|
||||
|
||||
data ->
|
||||
Socket.Web.send!(socket, {:text, Poison.encode!(data)})
|
||||
socket_loop(socket, cb)
|
||||
after
|
||||
500 -> socket_loop(socket, cb)
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_data(%{"type" => "hello"}, socket, _) do
|
||||
Logger.success(3, "Connected to slack!")
|
||||
|
||||
msg =
|
||||
%{
|
||||
type: "message",
|
||||
id: 1,
|
||||
channel: "C58DCU4A3",
|
||||
text: ":farmbot-genesis: #{node()} Connected!"
|
||||
}
|
||||
|> Poison.encode!()
|
||||
|
||||
Socket.Web.send!(socket, {:text, msg})
|
||||
end
|
||||
|
||||
defp handle_data(msg, _socket, cb), do: send(cb, {:socket, msg})
|
||||
end
|
||||
|
||||
def upload_file(file, channels \\ "C58DCU4A3") do
|
||||
GenServer.call(__MODULE__, {:upload_file, file, channels}, :infinity)
|
||||
end
|
||||
|
||||
def start_link() do
|
||||
GenServer.start_link(__MODULE__, @token, name: __MODULE__)
|
||||
end
|
||||
|
||||
def init(nil) do
|
||||
Logger.warn(3, "Not setting up slack (No slack token)")
|
||||
:ignore
|
||||
end
|
||||
|
||||
def init(token) do
|
||||
url = "https://slack.com/api/rtm.connect"
|
||||
payload = {:multipart, [{"token", token}]}
|
||||
headers = [{'User-Agent', 'Farmbot HTTP Adapter'}]
|
||||
|
||||
with {:ok, %{status_code: 200, body: body}} <- HTTPoison.post(url, payload, headers),
|
||||
{:ok, %{"ok" => true} = results} <- Poison.decode(body),
|
||||
{:ok, url} <- Map.fetch(results, "url"),
|
||||
{:ok, pid} <- RTMSocket.start_link(url, self()) do
|
||||
Process.link(pid)
|
||||
{:ok, %{rtm_socket: pid, token: token, updating: false}}
|
||||
else
|
||||
{:error, :invalid, _} ->
|
||||
init(token)
|
||||
|
||||
{:ok, %{status_code: code}} ->
|
||||
Logger.error(2, "Failed get RTM Auth: #{code}")
|
||||
:ignore
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error(2, "Failed to get RTM Auth: #{inspect(reason)}")
|
||||
:ignore
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call({:upload_file, file, channels}, _from, state) do
|
||||
file = to_string(file)
|
||||
|
||||
payload =
|
||||
%{
|
||||
:file => file,
|
||||
"token" => state.token,
|
||||
"channels" => channels,
|
||||
"title" => file,
|
||||
"initial_comment" => ""
|
||||
}
|
||||
|> Map.to_list()
|
||||
|
||||
real_payload = {:multipart, payload}
|
||||
url = "https://slack.com/api/files.upload"
|
||||
headers = [{'User-Agent', 'Farmbot HTTP Adapter'}]
|
||||
|
||||
case HTTPoison.post(url, real_payload, headers, follow_redirect: true) do
|
||||
{:ok, %{status_code: code, body: body}} when code > 199 and code < 300 ->
|
||||
if Poison.decode!(body) |> Map.get("ok", false) do
|
||||
:ok
|
||||
else
|
||||
Logger.error(3, "#{inspect(Poison.decode!(body, pretty: true))}")
|
||||
end
|
||||
|
||||
other ->
|
||||
Logger.error(3, "#{inspect(other)}")
|
||||
end
|
||||
|
||||
{:reply, :ok, state}
|
||||
end
|
||||
|
||||
def handle_info(
|
||||
{:socket, %{"file" => %{"url_private_download" => dl_url, "name" => name}}},
|
||||
state
|
||||
) do
|
||||
if Path.extname(name) == ".fw" do
|
||||
if match?(<<(<<"farmbot-">>), @target, <<"-">>, _rest::binary>>, name) do
|
||||
Logger.warn(3, "Downloading and applying an image from slack!")
|
||||
|
||||
if Farmbot.System.ConfigStorage.get_config_value(:bool, "settings", "os_auto_update") do
|
||||
dl_fun = Farmbot.BotState.download_progress_fun("FBOS_OTA")
|
||||
|
||||
case Farmbot.HTTP.download_file(dl_url, Path.join(@data_path, name), dl_fun, "", [
|
||||
{'Authorization', 'Bearer #{state.token}'}
|
||||
]) do
|
||||
{:ok, path} ->
|
||||
Farmbot.System.Updates.apply_firmware(path, true)
|
||||
{:stop, :normal, %{state | updating: true}}
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error(3, "Failed to download update file: #{inspect(reason)}")
|
||||
{:noreply, state}
|
||||
end
|
||||
else
|
||||
Logger.warn(3, "Not downloading debug update because auto updates are disabled.")
|
||||
{:noreply, state}
|
||||
end
|
||||
else
|
||||
Logger.debug(3, "Not downloading #{name} (wrong target)")
|
||||
{:noreply, state}
|
||||
end
|
||||
else
|
||||
{:noreply, state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({:socket, _msg}, state), do: {:noreply, state}
|
||||
|
||||
def terminate(reason, state) do
|
||||
if Process.alive?(state.rtm_socket) do
|
||||
send(state.rtm_socket, {:stop, reason})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -31,7 +31,7 @@ defmodule Farmbot.System.UpdateTimer do
|
|||
|
||||
def handle_info(:checkup, state) do
|
||||
osau = Farmbot.System.ConfigStorage.get_config_value(:bool, "settings", "os_auto_update")
|
||||
Farmbot.System.Updates.check_updates(osau)
|
||||
# Farmbot.System.Updates.check_updates(osau)
|
||||
Process.send_after(self(), :checkup, @twelve_hours)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
|
|
@ -3,10 +3,6 @@ defmodule Farmbot.System.Updates do
|
|||
use Supervisor
|
||||
|
||||
@data_path Application.get_env(:farmbot, :data_path)
|
||||
@current_version Farmbot.Project.version()
|
||||
@target Farmbot.Project.target()
|
||||
@current_commit Farmbot.Project.commit()
|
||||
@env Farmbot.Project.env()
|
||||
use Farmbot.Logger
|
||||
|
||||
@handler Application.get_env(:farmbot, :behaviour)[:update_handler]
|
||||
|
@ -16,152 +12,206 @@ defmodule Farmbot.System.Updates do
|
|||
|
||||
@doc "Overwrite os update server field"
|
||||
def override_update_server(url) do
|
||||
ConfigStorage.update_config_value(:bool, "settings", "beta_opt_in", true)
|
||||
ConfigStorage.update_config_value(:string, "settings", "os_update_server_overwrite", url)
|
||||
end
|
||||
|
||||
@doc "Force check updates."
|
||||
def check_updates(reboot) do
|
||||
if @handler.requires_reboot? do
|
||||
if reboot do
|
||||
Logger.info 1, "Farmbot applied an update. Rebooting."
|
||||
Farmbot.System.reboot("Update reboot required")
|
||||
else
|
||||
Logger.info 1, "Farmbot already applied an update. Please reboot."
|
||||
:ok
|
||||
end
|
||||
else
|
||||
token = ConfigStorage.get_config_value(:string, "authorization", "token")
|
||||
if token do
|
||||
case Farmbot.Jwt.decode(token) do
|
||||
{:ok, %Farmbot.Jwt{os_update_server: normal_update_server, beta_os_update_server: beta_update_server}} ->
|
||||
override = ConfigStorage.get_config_value(:string, "settings", "os_update_server_overwrite")
|
||||
if ConfigStorage.get_config_value(:bool, "settings", "beta_opt_in") do
|
||||
do_check_updates_http(override || beta_update_server, reboot)
|
||||
else
|
||||
do_check_updates_http(override || normal_update_server, reboot)
|
||||
end
|
||||
_ -> no_token()
|
||||
end
|
||||
else
|
||||
no_token()
|
||||
end
|
||||
defmodule Release do
|
||||
defmodule Asset do
|
||||
defstruct [
|
||||
:name,
|
||||
:browser_download_url
|
||||
]
|
||||
end
|
||||
|
||||
defstruct [
|
||||
tag_name: nil,
|
||||
target_commitish: nil,
|
||||
name: nil,
|
||||
draft: false,
|
||||
prerelease: true,
|
||||
body: nil,
|
||||
assets: []
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
defmodule CurrentStuff do
|
||||
import Farmbot.Project
|
||||
defstruct [
|
||||
:token,
|
||||
:beta_opt_in,
|
||||
:os_update_server_overwrite,
|
||||
:env,
|
||||
:commit,
|
||||
:target,
|
||||
:version
|
||||
]
|
||||
|
||||
def get(replace \\ %{}) do
|
||||
os_update_server_overwrite = ConfigStorage.get_config_value(:string, "settings", "os_update_server_overwrite")
|
||||
beta_opt_in? = is_binary(os_update_server_overwrite) || ConfigStorage.get_config_value(:bool, "settings", "beta_opt_in")
|
||||
token_bin = ConfigStorage.get_config_value(:string, "authorization", "token")
|
||||
token = if token_bin, do: Farmbot.Jwt.decode!(token_bin), else: nil
|
||||
opts = %{
|
||||
token: token,
|
||||
beta_opt_in: beta_opt_in?,
|
||||
os_update_server_overwrite: os_update_server_overwrite,
|
||||
env: env(),
|
||||
commit: commit(),
|
||||
target: target(),
|
||||
version: version()
|
||||
} |> Map.merge(Map.new(replace))
|
||||
struct(__MODULE__, opts)
|
||||
end
|
||||
end
|
||||
|
||||
defp no_token do
|
||||
Logger.debug 3, "Not checking for updates. (No token)"
|
||||
:ok
|
||||
@doc """
|
||||
Force check for updates.
|
||||
Does _NOT_ download or apply update.
|
||||
"""
|
||||
# @spec check_updates(Release.t | nil) ::
|
||||
def check_updates(release \\ nil, current_stuff \\ nil)
|
||||
|
||||
def check_updates(nil, current_stuff) do
|
||||
current_stuff_mut = %{
|
||||
token: token,
|
||||
beta_opt_in: beta_opt_in,
|
||||
os_update_server_overwrite: server_override,
|
||||
env: env,
|
||||
} = current_stuff || CurrentStuff.get()
|
||||
cond do
|
||||
env != :prod -> {:error, :wrong_env}
|
||||
is_nil(token) -> {:error, :no_token}
|
||||
is_binary(server_override) ->
|
||||
Logger.debug 3, "Update server override: #{server_override}"
|
||||
get_release_from_url(server_override)
|
||||
beta_opt_in ->
|
||||
Logger.debug 3, "Checking for beta updates."
|
||||
token
|
||||
|> Map.get(:beta_os_update_server)
|
||||
|> get_release_from_url()
|
||||
true ->
|
||||
Logger.debug 3, "Checking for production updates."
|
||||
token
|
||||
|> Map.get(:os_update_server)
|
||||
|> get_release_from_url()
|
||||
end
|
||||
|> case do
|
||||
%Release{} = release when beta_opt_in ->
|
||||
do_check_production_release = fn() ->
|
||||
token
|
||||
|> Map.get(:os_update_server)
|
||||
|> get_release_from_url()
|
||||
|> case do
|
||||
%Release{} = prod_release -> check_updates(prod_release, current_stuff_mut)
|
||||
err -> err
|
||||
end
|
||||
end
|
||||
check_updates(release, current_stuff_mut) || do_check_production_release.()
|
||||
%Release{} = release -> check_updates(release, current_stuff_mut)
|
||||
err -> err
|
||||
end
|
||||
end
|
||||
|
||||
defp do_check_updates_http(url, reboot) do
|
||||
Logger.info 3, "Checking: #{url} for updates."
|
||||
with {:ok, %{body: body, status_code: 200}} <- Farmbot.HTTP.get(url),
|
||||
{:ok, data} <- Poison.decode(body),
|
||||
{:ok, prerelease} <- Map.fetch(data, "prerelease"),
|
||||
{:ok, new_commit} <- Map.fetch(data, "target_commitish"),
|
||||
{:ok, cl} <- Map.fetch(data, "body"),
|
||||
{:ok, false} <- Map.fetch(data, "draft"),
|
||||
{:ok, "v" <> new_version_str} <- Map.fetch(data, "tag_name"),
|
||||
{:ok, new_version} <- Version.parse(new_version_str),
|
||||
{:ok, current_version} <- Version.parse(@current_version),
|
||||
{:ok, fw_url} <- find_fw_url(data, new_version) do
|
||||
needs_update = if prerelease do
|
||||
val = new_commit == @current_commit
|
||||
Logger.info 1, "Checking prerelease commits: current_commit: #{@current_commit} new_commit: #{new_commit} #{val}"
|
||||
!val
|
||||
else
|
||||
case Version.compare(current_version, new_version) do
|
||||
s when s in [:gt, :eq] ->
|
||||
Logger.success 2, "Farmbot is up to date."
|
||||
false
|
||||
:lt ->
|
||||
Logger.busy 1, "New Farmbot firmware update: #{new_version}"
|
||||
true
|
||||
def check_updates(%Release{} = rel, %CurrentStuff{} = current_stuff) do
|
||||
%{
|
||||
beta_opt_in: beta_opt_in,
|
||||
commit: current_commit,
|
||||
version: current_version
|
||||
} = current_stuff
|
||||
|
||||
release_version = String.trim(rel.tag_name, "v") |> Version.parse!()
|
||||
is_beta_release? = "beta" in (release_version.pre || [])
|
||||
version_comp = Version.compare(current_version, release_version)
|
||||
|
||||
release_commit = rel.target_commitish
|
||||
commits_equal? = current_commit == release_commit
|
||||
|
||||
prerelease = rel.prerelease
|
||||
cond do
|
||||
# Don't bother if the release is a draft. Not sure how/if this can happen.
|
||||
rel.draft ->
|
||||
Logger.warn 1, "Not checking draft release."
|
||||
nil
|
||||
|
||||
# Only check prerelease if
|
||||
# current_version is less than or equal to release_version
|
||||
# AND
|
||||
# the commits are not equal.
|
||||
prerelease and is_beta_release? and beta_opt_in and !commits_equal? ->
|
||||
# beta release get marked as greater than non beta release, so we need
|
||||
# to manually check the versions by removing the pre part.
|
||||
case Version.compare(current_version, %{release_version | pre: nil}) do
|
||||
c when c in [:lt, :eq] ->
|
||||
Logger.debug 3, "Current version (#{current_version}) is less than or equal to beta release (#{release_version})"
|
||||
try_find_dl_url_in_asset(rel.assets, release_version, current_stuff)
|
||||
:gt ->
|
||||
Logger.debug 3, "Current version (#{current_version}) is greater than latest beta release (#{release_version})"
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
# if the current version is less than the release version.
|
||||
!prerelease and version_comp == :lt ->
|
||||
Logger.debug 3, "Current version is less than release."
|
||||
try_find_dl_url_in_asset(rel.assets, release_version, current_stuff)
|
||||
|
||||
if should_apply_update(@env, prerelease, needs_update) do
|
||||
Logger.busy 1, "Downloading FarmbotOS over the air update"
|
||||
IO.puts cl
|
||||
# Logger.info 1, "Downloading update. Here is the release notes"
|
||||
# Logger.info 1, cl
|
||||
do_download_and_apply(fw_url, new_version, reboot)
|
||||
else
|
||||
:no_update
|
||||
end
|
||||
# If the version isn't different, but the commits are different,
|
||||
# This happens for beta releases.
|
||||
!prerelease and version_comp == :eq and !commits_equal? ->
|
||||
Logger.debug 3, "Current version is equal to release, but commits are not equal."
|
||||
try_find_dl_url_in_asset(rel.assets, release_version, current_stuff)
|
||||
|
||||
true ->
|
||||
comparison_str = "version check: current version: #{current_version} #{version_comp} latest release version: #{release_version} \n"<>
|
||||
"commit check: current commit: #{current_commit} latest release commit: #{release_commit}: (equal: #{commits_equal?})"
|
||||
|
||||
Logger.debug 3, "No updates available: \ntarget: #{Farmbot.Project.target()}: \nprerelease: #{prerelease} \n#{comparison_str}"
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def try_find_dl_url_in_asset(assets, version, current_stuff)
|
||||
|
||||
def try_find_dl_url_in_asset([%Release.Asset{name: name, browser_download_url: bdurl} | rest], release_version, current_stuff) do
|
||||
release_version = to_string(release_version)
|
||||
current_target = to_string(current_stuff.target)
|
||||
expected_name = "farmbot-#{current_target}-#{release_version}.fw"
|
||||
if match?(^expected_name, name) do
|
||||
bdurl
|
||||
else
|
||||
:error ->
|
||||
msg = "Unexpected release HTTP response or wrong formated `tag_name`"
|
||||
Logger.error 2, msg
|
||||
Logger.debug 3, "Incorrect asset name for target: #{current_target}: #{name}"
|
||||
try_find_dl_url_in_asset(rest, release_version, current_stuff)
|
||||
end
|
||||
end
|
||||
|
||||
{:error, :no_fw_url} ->
|
||||
Logger.error 2, "No firmware in update asssets."
|
||||
def try_find_dl_url_in_asset([], release_version, current_stuff) do
|
||||
Logger.warn 2, "No update in assets for #{current_stuff.target()} for #{release_version}"
|
||||
nil
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error 1, "Failed to fetch update data: #{inspect reason}"
|
||||
|
||||
{:ok, %{status_code: 400}} ->
|
||||
Logger.info 2, "Had out of date token. Try that again."
|
||||
def get_release_from_url(url) when is_binary(url) do
|
||||
Logger.debug 3, "Checking for updates: #{url}"
|
||||
case http_adapter().get(url) do
|
||||
{:ok, %{status_code: 404}} ->
|
||||
Logger.warn 1, "Got a 404 checking for updates: #{url}. Fetching a new token. Try that again"
|
||||
Farmbot.Bootstrap.AuthTask.force_refresh()
|
||||
|
||||
{:ok, %{body: body, status_code: code}} ->
|
||||
reason = case Poison.decode(body) do
|
||||
{:ok, res} -> res
|
||||
_ -> body
|
||||
{:error, :token_refresh}
|
||||
{:ok, %{status_code: 200, body: body}} ->
|
||||
pattern = struct(Release, [assets: [struct(Release.Asset)]])
|
||||
case Poison.decode(body, as: pattern) do
|
||||
{:ok, %Release{} = rel} -> rel
|
||||
_err -> {:error, :bad_release_body}
|
||||
end
|
||||
Logger.error 1, "OS Update HTTP error: #{code}: #{inspect reason}"
|
||||
{:ok, %{status_code: _code, body: body}} ->
|
||||
{:error, body}
|
||||
err -> err
|
||||
end
|
||||
end
|
||||
|
||||
defp find_fw_url(%{"assets" => assets}, version) do
|
||||
expected_name = "farmbot-#{@target}-#{version}.fw"
|
||||
res = Enum.find_value(assets, fn(asset) ->
|
||||
case asset do
|
||||
%{"browser_download_url" => fw_url, "name" => ^expected_name} -> fw_url
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
|
||||
if res do
|
||||
{:ok, res}
|
||||
else
|
||||
{:error, :no_fw_url}
|
||||
end
|
||||
end
|
||||
|
||||
defp should_apply_update(env, prerelease?, needs_update?)
|
||||
defp should_apply_update(_, _, false), do: false
|
||||
defp should_apply_update(:prod, true, _) do
|
||||
if ConfigStorage.get_config_value(:bool, "settings", "beta_opt_in") do
|
||||
Logger.info 3, "Applying beta update for production firmware"
|
||||
true
|
||||
else
|
||||
Logger.info 3, "Not applying prerelease update for production firmware"
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp should_apply_update(_env, true, _) do
|
||||
Logger.info 3, "Applying prerelease firmware."
|
||||
true
|
||||
end
|
||||
|
||||
defp should_apply_update(_, _, true) do
|
||||
true
|
||||
end
|
||||
|
||||
defp do_download_and_apply(dl_url, new_version, reboot) do
|
||||
dl_fun = Farmbot.BotState.download_progress_fun("FBOS_OTA")
|
||||
dl_path = Path.join(@data_path, "#{new_version}.fw")
|
||||
case Farmbot.HTTP.download_file(dl_url, dl_path, dl_fun, "", []) do
|
||||
{:ok, path} ->
|
||||
apply_firmware(path, reboot)
|
||||
{:error, reason} ->
|
||||
Logger.error 1, "Failed to download update file: #{inspect reason}"
|
||||
{:error, reason}
|
||||
end
|
||||
def http_adapter do
|
||||
# adapter = Application.get_env(:farmbot, :behaviour)[:http_adapter]
|
||||
# adapter || raise "No http adapter!"
|
||||
Farmbot.HTTP
|
||||
end
|
||||
|
||||
@doc "Apply an OS (fwup) firmware."
|
||||
|
@ -204,7 +254,8 @@ defmodule Farmbot.System.Updates do
|
|||
|
||||
@doc false
|
||||
def start_link do
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
:ignore
|
||||
# Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
defmodule Farmbot.System.UpdatesTest do
|
||||
use ExUnit.Case, async: false
|
||||
alias Farmbot.System.Updates
|
||||
alias Farmbot.System.Updates.{Release, CurrentStuff}
|
||||
@old_version Farmbot.Project.version |> Version.parse! |> Map.update(:major, nil, &Kernel.-(&1, 1)) |> to_string()
|
||||
|
||||
describe "CurrentStuff replacement" do
|
||||
test "replaces valid things in the current stuff struct" do
|
||||
r = CurrentStuff.get(env: :almost_prod)
|
||||
assert r.env == :almost_prod
|
||||
end
|
||||
|
||||
test "Allows and igrnores arbitry data" do
|
||||
r = CurrentStuff.get(some_key: :some_val)
|
||||
refute Map.get(r, :some_key)
|
||||
end
|
||||
end
|
||||
|
||||
test "checks for updates for prod rpi3 no beta combo" do
|
||||
# updating from old to new version should work
|
||||
current = CurrentStuff.get(os_update_server_overwrite: nil, beta_opt_in: false, env: :prod, target: :rpi3, version: @old_version)
|
||||
assert Updates.check_updates(nil, current)
|
||||
end
|
||||
|
||||
test "checks for updates for prod rpi3 with beta combo" do
|
||||
# old version to later beta
|
||||
current = CurrentStuff.get(os_update_server_overwrite: nil, env: :prod, target: :rpi3, version: @old_version, beta_opt_in: true)
|
||||
assert Updates.check_updates(nil, current)
|
||||
end
|
||||
|
||||
end
|
|
@ -2,7 +2,7 @@
|
|||
unless '--exclude farmbot_api' in :init.get_plain_arguments() do
|
||||
FarmbotTestSupport.preflight_checks()
|
||||
end
|
||||
Farmbot.Logger.Console.set_verbosity_level(0)
|
||||
# Farmbot.Logger.Console.set_verbosity_level(0)
|
||||
|
||||
Ecto.Adapters.SQL.Sandbox.mode(Farmbot.Repo.A, :manual)
|
||||
Ecto.Adapters.SQL.Sandbox.mode(Farmbot.Repo.B, :manual)
|
||||
|
|
Loading…
Reference in New Issue