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()
endup/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 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
@spec down() :: :ok
Drops the flags table and the usage table. Call from the down/0 of your
own migration.
@spec down_usage() :: :ok
Drops the usage table.
@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
endSafe 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).
@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.
@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()
endThe 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.
@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()
endUses 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.