Bandera.Ecto.Migrations (bandera v0.5.0)

Copy Markdown View Source

Helpers for creating Bandera's tables. Call from your own migration:

defmodule MyApp.Repo.Migrations.CreateBandera do
  use Ecto.Migration
  def up, do: Bandera.Ecto.Migrations.up()
  def down, do: Bandera.Ecto.Migrations.down()
end

up/0 creates both the flags table and the usage table (for stale-flag detection). Existing installs that already have the flags table can add just the usage table via up_usage/0 from a new migration.

Table names are read at runtime from config :bandera, persistence: [...] (ecto_table_name, default "bandera_flags"; usage_table_name, default "bandera_usage"), so they are never fixed at compile time.

Summary

Functions

Drops the flags table and the usage table. Call from the down/0 of your own migration.

Drops the usage table.

Fixes boolean gate rows left by a FunWithFlags-to-Bandera migration.

Creates the flags table (and its index) plus the usage table, idempotently.

Creates the usage table for durable stale-flag detection (idempotently).

Add the schema-v2 value column to an existing flags table.

Functions

down()

@spec down() :: :ok

Drops the flags table and the usage table. Call from the down/0 of your own migration.

down_usage()

@spec down_usage() :: :ok

Drops the usage table.

fix_fun_with_flags_boolean_gates()

@spec fix_fun_with_flags_boolean_gates() :: :ok

Fixes boolean gate rows left by a FunWithFlags-to-Bandera migration.

FunWithFlags stored boolean gates with a legacy target value; Bandera uses "_bandera_none". Because the Ecto adapter's upsert conflict target is (flag_name, gate_type, target), toggling a flag via Bandera after migration inserts a second boolean row rather than updating the legacy one. This leaves two rows with contradictory enabled values, causing the dashboard toggle and summary to disagree and making the toggle appear broken.

Run once from a migration after switching to Bandera:

defmodule MyApp.Repo.Migrations.FixFunWithFlagsBooleanGates do
  use Ecto.Migration
  def up, do: Bandera.Ecto.Migrations.fix_fun_with_flags_boolean_gates()
  def down, do: :ok
end

Safe to run on a database that has already been fully migrated — it will find nothing to change. Not reversible (down should be a no-op).

up()

@spec up() :: :ok

Creates the flags table (and its index) plus the usage table, idempotently.

Call from the up/0 of your own migration. Table names are read at runtime from Bandera.Config. New installs get everything in one migration; uses create_if_not_exists throughout so it is safe on all SQL backends.

up_usage()

@spec up_usage() :: :ok

Creates the usage table for durable stale-flag detection (idempotently).

New installs get this automatically via up/0. Existing Bandera installs should call it from a separate migration to add the table without touching the flags table:

defmodule MyApp.Repo.Migrations.CreateBanderaUsage do
  use Ecto.Migration
  def up, do: Bandera.Ecto.Migrations.up_usage()
  def down, do: Bandera.Ecto.Migrations.down_usage()
end

The table stores one row per flag — the timestamp it was last evaluated anywhere in the fleet. Bandera.Usage flushes to this table periodically (default every 10 minutes) and seeds ETS from it at startup.

upgrade_v2()

@spec upgrade_v2() :: :ok

Add the schema-v2 value column to an existing flags table.

Call once from the up/0 of a versioned migration in an existing install:

defmodule MyApp.Repo.Migrations.UpgradeBanderaV2 do
  use Ecto.Migration
  def up, do: Bandera.Ecto.Migrations.upgrade_v2()
end

Uses a plain add/2 (not add_if_not_exists/2) so it works on adapters such as SQLite3 that reject conditional column additions; migration versioning ensures it runs only once.