Thanks for your interest in Bier! This guide collects the project-specific
rules that are easy to trip over; the README covers the
architecture and docs/CONFORMANCE_IMPL.md covers the
conformance build in depth.
Everything below assumes a git checkout — several files it refers to
(mise.toml, spec/, docs/CONFORMANCE_IMPL.md) are repository-only and are
not part of the published package or documentation.
Toolchain
Elixir/OTP versions are pinned in mise.toml (Elixir 1.20 / OTP 29), matching
CI. mix.exs declares the lower bound at ~> 1.18. With
mise installed:
mise install
mix deps.get
A local PostgreSQL (15+) reachable at localhost:5432 is required for the
test suite, with the PostGIS extension available (mix bier.fixtures.load
runs CREATE EXTENSION IF NOT EXISTS postgis for the geo+json conformance
cases; CI uses the postgis/postgis images). Connection parameters come from
the standard PG* environment variables (PGHOST, PGPORT, PGUSER,
PGPASSWORD).
Running the suite
mix test # loads the fixture DB, runs everything
mix test test/path/to/file_test.exs:LINE # a single test
mix test --only area:operators # one conformance area
mix test is aliased to ["bier.fixtures.load", "test"]: it drops and
recreates a local bier_test database and loads
spec/conformance/fixtures.sql before running, so it is always safe to re-run.
The golden rule: test/** and spec/** are frozen
The conformance suite (762 cases in spec/, executed by
test/conformance/conformance_test.exs) encodes real PostgREST v16.0
behavior, with each case citing its upstream source. It is ground truth:
- Fix
lib/to match the cases — never edittest/**orspec/**. - If a case looks wrong, re-check the cited PostgREST source before assuming the test is at fault.
Generated code
lib/bier/query_parser.ex is generated from its
lib/bier/query_parser.ex.exs template. Edit the template, run
mix gen.parsers, and commit both the template and the regenerated .ex.
Never edit the generated .ex directly. Credo analyzes the template
(the file you edit) but skips the generated output.
Before you push
Run all of CI's gates with one command:
mix precommit
It is an alias (see mix.exs) for the individual gates, in order:
mix deps.unlock --check-unused
mix format --check-formatted
mix hex.audit
mix compile --warnings-as-errors
mix credo --strict
mix docs --warnings-as-errors
mix test
CI runs the same steps individually (not the alias) so each gate reports its
result separately. The test step is a plain mix test with no tolerated
baseline: the suite passes today, and any failure fails the job.
Style
mix formatsettles formatting arguments; Credo (.credo.exs) settles the rest. Both run in CI.- Serialize JSON through
Bier.json_library(), never by calling a JSON module directly, so host applications can swap the encoder. - New error shapes belong in
Bier.Plugs.FallbackControlleras additionalcall/2clauses, not inline in the controllers. - Public modules carry a
@moduledocexplaining why the module exists and which PostgREST behavior it mirrors; keep that bar for new code.