Skip to content

Private Dependencies

bharendt edited this page May 25, 2016 · 1 revision

Private Dependencies

1) Agent Forwarding

edeliver uses ssh agent forwarding when building the release or upgrade on the build host.

This allows to access private repositories as long as the private key is available on the local (development) machine that runs the edeliver command. This enables you e.g. to access a private repository on github without installing your private key on the build host:

# mix.exs
defp deps do
  [
    # private git repository as dependency
    {:private_dep, "1.2.3", git: "git@github.com:my_company/private_repo.git"}
  ]
end

In addition you can also use one of the other options to make private dependencies available on the build host:

2) Private Key on Build host

Of course you can also install (additional) private ssh keys to access (other) private repositories on your build host.

3) Path Dependency

Install your libary which is a private dependency on your build host e.g at /usr/lib/your_private_dep (and preferably on your development hosts at the same location) and use the mix path: option for your dependency:

# mix.exs
defmodule YourApp.Mixfile do
  use Mix.Project

  def project do
   [
     app: :your_app,
     deps: [
       {:phoenix_html, "..."}, # mix dependency
       # path dependency
       {:your_private_dep, path: "/usr/lib/your_private_dep"}, 
       ....

4) Pre Hook

Use an edeliver pre-hook in your .deliver/config which somehow gets the dependency:

  # .deliver/config
  ...
  pre_erlang_get_and_update_deps() {
    __sync_remote " # execute on build host
      # e.g. copy the dependency from some source on the build host
      cp -R /usr/lib/your_private_dep ${BUILD_AT}/deps/your_private_dep $SILENCE
      # or fetch it from some other scp / s3 / xy location
    "
  }

5) Linking Dependency

Link your dependency in deps/your_private_dep pointing to /usr/lib/your_private_dep and commit that link to your repository:

  ln -s /usr/lib/your_private_dep ./deps/your_private_dep
  git add -f ./deps/your_private_dep
  git commit -m "linking private dep"

6) Mix SCM

Implement your own mix scm which fetches your private dependency somehow:

# mix.exs
Code.require_file "lib/mix/my_scm.exs", __DIR__
Mix.SCM.append  MyApp.SCM.MySCM
defmodule YourApp.Mixfile do
  use Mix.Project

  def project do
   [
     app: :your_app,
     deps: [
       {:your_private_dep, download: "url"}, # private dependency using your own scm, e.g download it 
 ...
# lib/mix/my_scm.exs
defmodule MyApp.SCM.MySCM do
  @behaviour Mix.SCM
  @moduledoc false

  def fetchable?, do: true
  def format(opts), do: opts[:download]
  def format_lock(_opts), do: {:download, true}

  def accepts_options(_app, opts) do
    case opts[:download] do
      <<_,_::binary>> -> opts
      _ -> nil
    end
  end

  def checked_out?(opts) do
    File.dir?(opts[:dest])
  end

  def checkout(opts) do
    # somehow fetch your private library, e.g. download from internal net
  end

  def lock_status(_opts), do: :ok
  def equal?(opts1, opts2), do: opts1[:download] == opts2[:download]
  def managers(_opts), do: []
  def update(opts), do: checkout(opts)
end

Option four (edeliver-pre-hook) and option five (linking the dep) might require to add your dependency as "fake" hex, path or git dependency to the deps config in your mix.exs to force mix to compile them, but as long as the version matches they should not be fetched by mix and the linked / copied dependency would be used instead.

When using option tree (file dependency) or five (linking the dep) you must keep your private library up to date yourself on the build host (and all development hosts).