Try to download pre-built bundles and fallback to building from source

This commit is contained in:
Roman Chvanikov 2020-07-28 17:49:30 +03:00
parent 90b237c273
commit cc7b7296a2
5 changed files with 114 additions and 57 deletions

View file

@ -30,24 +30,24 @@ defmodule Mix.Tasks.Pleroma.Frontend do
"none"
end
def run(["install", "all"]) do
def run(["install", "all" | options]) do
start_pleroma()
configs = Pleroma.Config.get(:frontends, %{})
with config when not is_nil(config) <- configs[:primary],
ref when ref != "none" <- config["ref"] do
run(["install", config["name"], "--ref", ref])
run(["install", config["name"], "--ref", ref | options])
end
with config when not is_nil(config) <- configs[:mastodon],
ref when ref != "none" <- config["ref"] do
run(["install", "mastodon", "--ref", ref])
run(["install", "mastodon", "--ref", ref | options])
end
with config when not is_nil(config) <- configs[:admin],
ref when ref != "none" <- config["ref"] do
run(["install", "admin", "--ref", ref])
run(["install", "admin", "--ref", ref | options])
end
end
@ -106,32 +106,67 @@ defmodule Mix.Tasks.Pleroma.Frontend do
fe_label = "#{frontend} (#{ref})"
from =
{from, proceed?} =
with nil <- options[:path] do
Pleroma.Utils.command_required!("yarn")
url = archive_url(frontend, ref)
tmp_dir = Path.join(dest, "tmp/src")
shell_info("Downloading #{fe_label} to #{tmp_dir}")
:ok = download_frontend(url, tmp_dir)
shell_info("Downloading pre-built bundle for #{fe_label}")
shell_info("Building #{fe_label} (this will take some time)")
:ok = build_frontend(frontend, tmp_dir)
tmp_dir
proceed? =
with {:error, error} <- download_frontend(frontend, ref, tmp_dir, :build) do
shell_info("Could not download pre-built bundle: #{inspect(error)}.")
shell_info("Falling back to building locally from source")
download_and_build = fn callback ->
case Pleroma.Utils.command_available?("yarn") do
false ->
message =
"To build frontend #{fe_label} from sources, `yarn` command is required. Please install it before continue. ([C]ontinue/[A]bort)"
case String.downcase(shell_prompt(message, "C")) do
abort when abort in ["a", "abort"] ->
false
_continue ->
callback.(callback)
end
_ ->
shell_info("Downloading #{fe_label} sources to #{tmp_dir}")
:ok = download_frontend(frontend, ref, tmp_dir, :source)
shell_info("Building #{fe_label} (this will take some time)")
:ok = build_frontend(frontend, tmp_dir)
end
end
download_and_build.(download_and_build)
else
_ ->
true
end
{tmp_dir, proceed?}
else
path ->
{path, true}
end
shell_info("Installing #{fe_label} to #{dest}")
if proceed? do
shell_info("Installing #{fe_label} to #{dest}")
:ok = install_frontend(frontend, from, dest)
:ok = install_frontend(frontend, from, dest)
shell_info("Frontend #{fe_label} installed to #{dest}")
end
shell_info("Frontend #{fe_label} installed to #{dest}")
Logger.configure(level: log_level)
ref
end
defp download_frontend(url, dest) do
defp download_frontend(frontend, ref, dest, kind) do
url = frontend_url(frontend, ref, kind)
with {:ok, %{status: 200, body: zip_body}} <-
Pleroma.HTTP.get(url, [], timeout: 120_000, recv_timeout: 120_000),
{:ok, unzipped} <- :zip.unzip(zip_body, [:memory]) do
@ -139,8 +174,18 @@ defmodule Mix.Tasks.Pleroma.Frontend do
File.mkdir_p!(dest)
Enum.each(unzipped, fn {filename, data} ->
[_root | paths] = Path.split(filename)
path = Enum.join(paths, "/")
path =
case kind do
:source ->
filename
|> Path.split()
|> Enum.drop(1)
|> Enum.join("/")
:build ->
filename
end
new_file_path = Path.join(dest, path)
new_file_path
@ -151,10 +196,7 @@ defmodule Mix.Tasks.Pleroma.Frontend do
end)
else
{:ok, %{status: 404}} ->
{:error, "Bundle not found"}
false ->
{:error, "Zip archive must contain \"dist\" folder"}
{:error, "Zip archive with frontend #{kind} not found at #{url}"}
error ->
{:error, error}
@ -208,9 +250,16 @@ defmodule Mix.Tasks.Pleroma.Frontend do
URI.encode_www_form(@frontends[frontend]["project"])
}"
defp archive_url(frontend, ref),
defp source_url(frontend, ref),
do: "https://#{@pleroma_gitlab_host}/#{@frontends[frontend]["project"]}/-/archive/#{ref}.zip"
defp build_url(frontend, ref),
do:
"https://#{@pleroma_gitlab_host}/#{@frontends[frontend]["project"]}/-/jobs/artifacts/#{ref}/download?job=build"
defp frontend_url(frontend, ref, :source), do: source_url(frontend, ref)
defp frontend_url(frontend, ref, :build), do: build_url(frontend, ref)
defp local_path_frontend_ref(path) do
path
|> Path.join("package.json")

View file

@ -165,31 +165,16 @@ defmodule Mix.Tasks.Pleroma.Instance do
install_fe =
case Mix.env() do
:test ->
fn _, _ -> "42" end
fn _ -> "42" end
_ ->
fn frontend, callback ->
case Pleroma.Utils.command_available?("yarn") do
false when frontend != "none" ->
message =
"To install #{frontend} frontend, `yarn` command is required. Please install it before continue. ([C]ontinue/[A]bort)"
case String.downcase(shell_prompt(message, "C")) do
abort when abort in ["a", "abort"] ->
"none"
_continue ->
callback.(frontend, callback)
end
_ ->
Mix.Tasks.Pleroma.Frontend.run([
"install",
frontend,
"--static-dir",
static_dir
])
end
fn frontend ->
Mix.Tasks.Pleroma.Frontend.run([
"install",
frontend,
"--static-dir",
static_dir
])
end
end
@ -201,7 +186,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
"pleroma"
)
fe_primary_ref = install_fe.(fe_primary, install_fe)
fe_primary_ref = install_fe.(fe_primary)
enable_static_fe? =
get_option(
@ -222,7 +207,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
fe_mastodon_ref =
case install_mastodon_fe? do
true ->
install_fe.("mastodon", install_fe)
install_fe.("mastodon")
false ->
"none"
@ -238,7 +223,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
fe_admin_ref =
case install_admin_fe? do
true -> install_fe.("admin", install_fe)
true -> install_fe.("admin")
false -> "none"
end

BIN
test/fixtures/tesla_mock/fe-build.zip vendored Normal file

Binary file not shown.

View file

@ -8,7 +8,8 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
import Tesla.Mock, only: [mock_global: 1, json: 1]
@bundle_zip_path Path.absname("test/fixtures/tesla_mock/fe-bundle.zip")
@fe_source_zip_path Path.absname("test/fixtures/tesla_mock/fe-source.zip")
@fe_build_zip_path Path.absname("test/fixtures/tesla_mock/fe-build.zip")
@tmp "test/tmp"
@dir "#{@tmp}/instance_static"
@ -36,8 +37,17 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
|> Jason.decode!()
|> json()
%{method: :get, url: _download_url} ->
%Tesla.Env{status: 200, body: File.read!(@bundle_zip_path)}
%{method: :get, url: download_url} ->
cond do
String.contains?(download_url, "test-bundle") ->
%Tesla.Env{status: 200, body: File.read!(@fe_build_zip_path)}
String.ends_with?(download_url, "job=build") ->
%Tesla.Env{status: 404}
true ->
%Tesla.Env{status: 200, body: File.read!(@fe_source_zip_path)}
end
end)
File.mkdir_p!(@dir)
@ -71,7 +81,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
end
end
describe "Installation from web source" do
describe "Installation from source" do
test "develop" do
if Pleroma.Utils.command_available?("yarn") do
Mix.Tasks.Pleroma.Frontend.run([
@ -106,11 +116,24 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
end
end
describe "Installation from pre-built bundle" do
test "Installs pleroma" do
Mix.Tasks.Pleroma.Frontend.run([
"install",
"pleroma",
"--ref",
"test-bundle-1.2.3"
])
assert File.exists?(Path.join([@dir, "frontends/pleroma/test-bundle-1.2.3/index.html"]))
end
end
describe "Install all" do
test "Normal config" do
if Pleroma.Utils.command_available?("yarn") do
config = [
primary: %{"name" => "pleroma", "ref" => "1.2.3"},
primary: %{"name" => "pleroma", "ref" => "test-bundle-1.2.3"},
mastodon: %{"name" => "mastodon", "ref" => "2.3.4"},
admin: %{"name" => "admin", "ref" => "3.4.5"}
]
@ -118,7 +141,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
clear_config(:frontends, config)
Mix.Tasks.Pleroma.Frontend.run(["install", "all"])
assert File.exists?(Path.join([@dir, "frontends/pleroma/1.2.3/index.html"]))
assert File.exists?(Path.join([@dir, "frontends/pleroma/test-bundle-1.2.3/index.html"]))
assert File.exists?(Path.join([@dir, "frontends/mastodon/2.3.4/sw.js"]))
assert File.exists?(Path.join([@dir, "frontends/admin/3.4.5/index.html"]))
end