Gigalixir deploy fail: "module Config is not loaded and could not be found" "you appear to have cloned an empty repo"

Hi, I feel like I’m on the final leg of a marathon …

The app is really simple. Does one thing. Talks to Airtable, gets some json and wraps that into a .pdf. No db, no html. Only one thing I have to get right - where to put the Airtable authorisation token.
Production compiled and released and working at localhost:443. Everything for push to gigalixir seems correct, but it fails, so I’ve got something horribly wrong.

Here’s config.exs - I doubt it could be any shorter

config :app, AppWeb.Endpoint,
load_from_system_env: true
config :logger, level: :info
import_config “releases.exs”

I’m not sure about import_config "releases.exs. But I’ve renamed prod.secret.exs and that’s where the Airtable auth token now lives…

config :app,
airtable_api_key: “key”

And endpoint.ex now has the standard init function that seems to be well thumbed.

What piece of the jigsaw do I need to change? And could someone please write a clear tutorial for those like me who has just learned that “setting the port at build” means that I have to manually type and set it in the terminal :slight_smile:

Enumerating objects: 118, done.
Counting objects: 100% (118/118), done.
Delta compression using up to 8 threads
Compressing objects: 100% (110/110), done.
Writing objects: 100% (118/118), 29.48 KiB | 443.00 KiB/s, done.
Total 118 (delta 49), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (49/49), done.
remote: Starting deploy
remote: Preparing cache
remote: Compiling code and generating slug.
remote: Setting environment variables.
remote: * LIBCLUSTER_KUBERNETES_SELECTOR
remote: * LIBCLUSTER_KUBERNETES_NODE_BASENAME
remote: * APP_NAME
remote: * SECRET_KEY_BASE
remote: * PORT
remote: * SOURCE_VERSION
remote: Cloning into ‘studious-harmonious-redpoll’…
remote: warning: You appear to have cloned an empty repository.
remote: done.
remote: latest: Pulling from gigalixir-152404/build-18
remote: Digest: sha256:5fc09e182acefc099d28d2ec2ab75b3787a62d6798f01f001edc1e6e38785a1d
remote: Status: Image is up to date for us.gcr.io/gigalixir-152404/build-18:latest
remote: us.gcr.io/gigalixir-152404/build-18:latest
remote: -----> Detecting assets directory
remote: no package.json found
remote: Elixir+Releases app detected
remote: Detecting assets directory
remote: no package.json found
remote: =====> Downloading Buildpack: https://github.com/HashNuke/heroku-buildpack-elixir.git
remote: =====> Detected Framework: Elixir
remote: -----> Will export the following config vars:
remote: APP_NAME
remote: LIBCLUSTER_KUBERNETES_NODE_BASENAME
remote: LIBCLUSTER_KUBERNETES_SELECTOR
remote: PORT
remote: SECRET_KEY_BASE
remote: SOURCE_VERSION
remote: * MIX_ENV=prod
remote: -----> Checking Erlang and Elixir versions
remote: WARNING: elixir_buildpack.config wasn’t found in the app
remote: Using default config from Elixir buildpack
remote: Will use the following versions:
remote: * Stack heroku-18
remote: * Erlang 20.1
remote: * Elixir 1.5.3
remote: -----> Using cached Erlang 20.1
remote: -----> Installing Erlang 20.1
remote:
remote: -----> Using cached Elixir v1.5.3
remote: -----> Installing Elixir v1.5.3
remote: -----> Installing Hex
remote: * creating /app/.mix/archives/hex-0.20.5
remote: -----> Installing rebar
remote: * creating /app/.mix/rebar
remote: * creating /app/.mix/rebar3
remote: -----> Fetching app dependencies with mix
remote: ** (Mix.Config.LoadError) could not load config config/config.exs
remote: ** (CompileError) config/config.exs:8: module Config is not loaded and could not be found
remote: (elixir) lib/code.ex:176: Code.eval_string/3
remote: (mix) lib/mix/config.ex:180: Mix.Config.read!/2
remote: Deploy aborted
To https://git.gigalixir.com/studious-harmonious-redpoll.git/
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to ‘https://git.gigalixir.com/studious-harmonious-redpoll.git/

I think I have to use init to read the airtable key, might have solved my problem…

Okay, so I # import_config “releases.exs” since https://hexdocs.pm/phoenix/releases.html says so.

The airtable key isn’t now held anywhere other than in dev.secret.exs (not much use for prod) and as a system environment variable.

I’ve updated init to include

airtable_key =
System.get_env(“AIRTABLE_KEY”) ||
raise(“expected the AIRTABLE_KEY environment variable to be set”)
|> Keyword.put(:airtable_api_key, airtable_key)

And in my code hope to find it using:
Application.fetch_env!(:app, :airtable_api_key)

Recompiling and releasing, but prod now fails on localhost. The variable isn’t set…

You are using Elixir v1.5 that doesn’t yet have the Config module, add elixir_buildpack.config and use v1.10 there. Also, you shouldn’t import releases.exs from prod.exs, these files have different purposes and are evaluated at different stages of deployment, prod.exs is for compile-time configuration and releases.exs is for runtime.

Finally, on Phoenix master there’s a new gigalixir deployment guide so definitely check it out!

4 Likes

Hi, thanks for the pointers, I’d only recently installed Elixir on this work laptop. I must have used the installer, but I’m installing 1.10.3 with chocolatey now.

I’m afraid I’d rather glossed over the .buildpack instruction on Gigalixir, having previously used distillery I thought it referred to going through that kind of build process.

elixir_buildpack.config now in my root with

elixir_version=1.10.3
erlang_version=22.3

But, I’m still not sure how gigalixir knows about the Airtable token - it’s a system environment variable on my laptop and it’s inside dev.secret.exs. I don’t have a good mental model of what to do with it for production :frowning:

That fixed the deployment to Gigalixir - thanks again for highlighting the absence of that file in my project.
I noticed this in the log:

remote: Setting environment variables.
remote: * LIBCLUSTER_KUBERNETES_SELECTOR
remote: * LIBCLUSTER_KUBERNETES_NODE_BASENAME
remote: * APP_NAME
remote: * SECRET_KEY_BASE
remote: * PORT
remote: * SOURCE_VERSION

But no mention of AIRTABLE_KEY … the app isn’t up yet, but I’m not expecting it to work when it is - fingers crossed

You can set environment variables on gigalixir with:

gigalixir config:set TOKEN=value

And then I’d read it in config/releases.exs with System.fetch_env!/1.

2 Likes

Thanks again, that fills key missing piece of my understanding - I have to set the variable on the server!

Is that the only place I need to reference the variable in the config / set-up?
I don’t need to alter the init function in endpoint.exs. That’s my intuition and I’ll try that first at least.

Update
Yep, that’s all gone well. Just in case anyone else passes this way and is as confused as I was about set-up and config this is my releases.ex file

import Config
config :app_name, AppWeb.Endpoint,
server: true,
http: [port: {:system, “PORT”}],
secret_key_base: System.fetch_env!(“SECRET_KEY_BASE”),
airtable_key: System.fetch_env!(“AIRTABLE_KEY”)

and in the code

defp token() do
case System.get_env(“AIRTABLE_KEY”) do
nil -> Application.fetch_env!(:sgre_hse_plan, :airtable_api_key)
key -> key
end

But I think I can dispense with the Application variable defined in dev.secret.exs for dev because it’s a System variable on my laptop too.

1 Like