mitgliederverwaltung/priv/repo/seeds.exs
Simon f8a3cc4c47
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
continuous-integration/drone/tag Build is passing
Run seeds only once (#475)
## Description of the implemented changes
The changes were:
- [ ] Bugfixing
- [x] New Feature
- [ ] Breaking Change
- [x] Refactoring

**Seeds run only on first startup.** On every application start (e.g. `just run`, Docker entrypoint), seed scripts are still invoked, but they exit immediately when the admin user already exists. This avoids duplicate seed data (e.g. join requests), keeps startup fast after the first run, and works the same in dev and production.

## What has been changed?

- **`lib/mv/release.ex`**
  - Added `bootstrap_seeds_applied?/0`: returns whether the admin user (from `ADMIN_EMAIL` or default `admin@localhost`) exists. We check the admin *user*, not the Admin *role*, so we do not skip when only migrations have run (migrations can create the Admin role for the system actor).
  - `run_seeds/0`: if `bootstrap_seeds_applied?()` is true, prints “Seeds already applied (admin user exists). Skipping.” and returns without running bootstrap or dev seeds; otherwise unchanged behaviour.
  - Module docs updated for the new function and the skip behaviour.

- **`priv/repo/seeds.exs`**
  - Ensures the app is started (`Application.ensure_all_started(:mv)`).
  - If `Mv.Release.bootstrap_seeds_applied?()` is true, prints the same skip message and does not run bootstrap or dev seeds; otherwise runs as before (bootstrap + dev seeds in dev/test).
  - Comment at the top updated to describe the skip behaviour.

- **Documentation**
  - `CODE_GUIDELINES.md` §1.2.1: seeds run on every start but exit early when already applied; mentions `bootstrap_seeds_applied?/0`.
  - `docs/admin-bootstrap-and-oidc-role-sync.md`: run_seeds skips when admin user exists; description of `run_seeds/0` updated.
  - `CHANGELOG.md` [Unreleased]: new “Seeds run only when needed” entry under Changed.

## Definition of Done
### Code Quality
- [x] No new technical depths
- [x] Linting passed
- [x] Documentation is added where needed

### Accessibility
- [x] New elements are properly defined with html-tags *(no new UI)*
- [x] Colour contrast follows WCAG criteria *(no new UI)*
- [x] Aria labels are added when needed *(no new UI)*
- [x] Everything is accessible by keyboard *(no new UI)*
- [x] Tab-Order is comprehensible *(no new UI)*
- [x] All interactive elements have a visible focus *(no new UI)*

### Testing
- [x] Tests for new code are written *(existing seeds and release tests cover behaviour; idempotency test still passes when second run skips)*
- [x] All tests pass
- [x] axe-core dev tools show no critical or major issues *(no UI changes)*

## Additional Notes

- **Review focus:** Logic in `Mv.Release` and `priv/repo/seeds.exs`; the “already applied” check is a single DB read for the admin user. On failure (e.g. DB down), `bootstrap_seeds_applied?/0` returns `false`, so seeds run (safe for first deploy).
- **Suggested check:** Run `mix test test/seeds_test.exs test/mv/release_test.exs` to confirm seeds and release behaviour.

Reviewed-on: #475
Co-authored-by: Simon <s.thiessen@local-it.org>
Co-committed-by: Simon <s.thiessen@local-it.org>
2026-03-16 19:27:31 +01:00

38 lines
1.5 KiB
Elixir

# Script for populating the database. You can run it as:
#
# mix run priv/repo/seeds.exs
#
# Bootstrap runs in all environments. Dev seeds (members, groups, sample data)
# run only in dev and test. Skips entirely if bootstrap was already applied
# (admin user exists), so safe to run on every start. Set FORCE_SEEDS=true to
# re-run seeds even when already applied.
#
# In production (release): seeds are run via Mv.Release.run_seeds/0 from the
# container entrypoint. Set RUN_DEV_SEEDS=true to also run dev seeds there.
#
# Compiler option ignore_module_conflict is set only during seed evaluation
# so that eval_file of bootstrap/dev does not emit "redefining module" warnings;
# it is always restored in `after` to avoid hiding real conflicts elsewhere.
_ = Application.ensure_all_started(:mv)
if Mv.Release.bootstrap_seeds_applied?() and System.get_env("FORCE_SEEDS") != "true" do
IO.puts("Seeds already applied. Skipping. (Set FORCE_SEEDS=true to override)")
else
prev = Code.compiler_options()
Code.compiler_options(ignore_module_conflict: true)
try do
# Always run bootstrap (fee types, custom fields, roles, admin, system user, settings)
Code.eval_file("priv/repo/seeds_bootstrap.exs")
# In dev and test only: run dev seeds (20 members, groups, custom field values)
if Mix.env() in [:dev, :test] do
Code.eval_file("priv/repo/seeds_dev.exs")
end
IO.puts("✅ All seeds completed.")
after
Code.compiler_options(prev)
end
end