defmodule Mix.Tasks.Monorepo.Export do @moduledoc """ Takes all the dependenceis of the project and exports as a .ez files. $ mix monorepo.export The export is always done for a combination of lockfile, arch, erlang/elixir vsns such that for every update in dependencies, versions or similar the archives must be rexported Only dependencies from hex are exported. """ @shortdoc "Export all dependencies as archives." use Mix.Task @impl true def run(_args) do env = Mix.env() Mix.Task.run(:compile, []) if dist = Mix.Project.config()[:monodist] do dist = Path.expand(dist) dir = Path.join([dist, "#{Mix.env()}", target()]) existing = Path.wildcard(Path.join([dist, "#{Mix.env()}", "**"])) deps = Mix.Dep.load_on_environment(only: env) lock = Mix.Dep.Lock.read() # Output the archives new = for %{app: app, status: status} <- deps do # Assume hex SCM manager {:ok, vsn} = status case lock[app] do nil -> # don't export archive not managed by hex nil lock -> {^app, ^vsn, chksum} = lock_meta(app, lock) output = Path.join([dir, "#{app}-#{vsn}-#{chksum}.ez"]) input = Path.join([Mix.Project.build_path(), "lib", "#{app}"]) # Only export if not already present if not File.exists?(output) do Mix.Task.rerun("archive.build", ["-i", input, "-o", output]) end output end end stale = existing -- [dir | new] # Remove old distribution files for old <- stale do IO.write(:stderr, "remove stale archive #{old}") File.rm_rf!(old) end end :ok end @doc """ Get the source checksum of from a lock """ def lock_meta(app, {:hex, app, vsn, _checksum, _mngr, _deps, _repo, chksum}), do: {app, vsn, String.slice(chksum, 0, 7)} def lock_meta(app, {:git, _remote, ref, _opts}), do: {app, ref, ref} # {:git, "https://github.com/lafka/elixir-keycloak.git", "650500fbd72b55847be3d81deb4b66ceafa99770", [ref: "650500fbd72b55847be3d81deb4b66ceafa99770"]} def lock_meta(app, nil), do: {app, nil, "0000000"} @doc """ Get runtime target """ def target() do arch = :erlang.system_info(:system_architecture) elixir_vsn = System.version() erlang_vsn = System.otp_release() Enum.join([arch, erlang_vsn, elixir_vsn], "-") end end