fireproofsocks

fireproofsocks

I’m missing something and I hope someone can point it out to me. Long story short, the first migration in my app needs to slurp up a dump file, e.g. init.sql. It sets does stuff like SET statement_timeout = 0 and CREATE SCHEMA core etc. (There are some historical reasons why we are using this).

Two things made this tricky:

  1. The Ecto repo didn’t use the normal name.
  2. The app that controls the repo is sometimes used as a dependency.

But we figured this out. The trick was a migration file that could point to the init.sql file, both when the app was used as the primary app OR when it gets used as a dependency. It boiled down to this (comments left in for transparency):

defmodule MyApp.PGRepo.Migrations.InitDb do
  use Ecto.Migration

  require Logger

  @doc """
  This is a "Mixless" way of running a custom migration.

  This migration must be flexible enough so we can run it from inside `my_app`
  or inside some other app that uses `my_app` as a dependency. We rely on
  `Ecto.Migration.repo/0` to tell us which repo is triggering the migration, and
  we use `:code.priv_dir/1` to infer the environment.
  """
  def change do
    # This magically knows which Repo is running the migrations
    # (it is important that we do not hard-code `MyApp.Repo`)
    repo = Ecto.Migration.repo()

    # [`c:Ecto.Adapter.Structure.structure_load/2`](https://hexdocs.pm/ecto_sql/Ecto.Adapter.Structure.html#c:structure_load/2)
    # REQUIRES the configuration to be broken out with individual keys
    # for username, password, etc.
    x = repo.__adapter__().structure_load(repo_path(), config(repo))
    Logger.debug(inspect(x))
  end

  # This migration must be flexible enough so we can run it from inside this app
  # or inside some other app that uses this as a dependency.
  defp repo_path do
    "#{:code.priv_dir(:my_app)}/pg_repo"
  end

  # This fetches the repo config and overrides the `:dump_path` to point to
  # the sql dump used to define the initial structure of the database.
  #
  # Do NOT use `Application.get_env(:my_app, Ecto.Migration.repo())`
  # because it will NOT parse out individual settings from a db URL!
  # Instead, use the [`c:Ecto.Repo.config/0`](https://hexdocs.pm/ecto/3.5.2/Ecto.Repo.html#c:config/0)
  # because this DOES parse out a db URL into its component parts (`:username`, `:password`, etc.).
  defp config(repo) do
    repo.config()
    |> Keyword.put(:dump_path, "#{repo_path()}/migrations/init.sql")
  end
end

The migrations get executed when we run tests on a PR on Github via Github actions. The github workflow is pretty straightforward, it contains (in part):

      - name: Compile
        run: mix compile

      - name: Create PostGres database
        run: mix ecto.create

      - name: Migrate PostGres database
        run: mix ecto.migrate

This has all been working fine.

Until… I copied this structure over to a new repo. And suddenly the init.sql file is not found when the Github workflow executes on the new repo. I added an inspection to the problematic line:

    x = repo.__adapter__().structure_load(repo_path(), config(repo))
    Logger.debug(inspect(x))

When I run tests etc. locally, it works fine. On Github, however, I get an error because the external file is not found:

_build/test/lib/my_app/priv/pg_repo/migrations/init.sql NOT FOUND

I’m not seeing anything between the 2 repos that would explain why the old app finds its init.sql file but the new app does not. Does anyone have any ideas of why the .sql file isn’t being found when the tests run externally in Github?

And, just to be thorough, I tried rewriting this first migration WITHOUT this weird .sql file, with something like this:

def change do
  # ...
  execute("CREATE SCHEMA core")
end

But this fails with a different error:

** (Postgrex.Error) ERROR 42P01 (undefined_table) relation "schema_migrations" does not exist

These are 2 different errors… I need to solve one of them to make migrations work (I don’t really care which one shakes out).

Thanks for any ideas!

Showing Posts 1 to 2

christhekeele

christhekeele

Does your release configuration copy all /priv/migrations over? Or maybe just .exs one?

fireproofsocks

fireproofsocks OP

Ah, this was the reality check I needed. I had created a global gitignore file that for some reason was ignoring .sql files, so that thing never made it up to Github. As soon as I committed that, things worked as expected.

The problem was between the keyboard and the chair.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews