# Makefile for Firehose monorepo MISE_BIN ?= mise .PHONY: check precommit verify hooks deps setup compile test test-elisp format # Cheap static gate over both apps, cheapest first. No database, no coverage: # this is the loop you run freely while working and before every commit. check: @echo "==> check: app (credo --strict, format)" @$(MAKE) -C app MISE_BIN=$(MISE_BIN) check @echo "==> check: blogex (compile, format)" @$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) check @echo "==> check: toolchain pins" @bash scripts/check-pins.sh @echo "==> check: Lens sensor wiring" @bash scripts/check-lens-sensors.sh # Precommit target for CI/pre-commit hooks precommit: check # The Lens pass: everything `check` does, plus, per app, one suite run (which # exports its coverage) and that app's sensors reading the export. Sensors run # cheapest-first among themselves. `.githooks/pre-push` runs this before every # push (see `make hooks`); run it yourself before handing off. Bypass # deliberately with `git push --no-verify`. verify: check @echo "==> verify: app" @$(MAKE) -C app MISE_BIN=$(MISE_BIN) verify @echo "==> verify: blogex" @$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) verify # Install the versioned hooks in .githooks/ into this clone's hooks directory as # symlinks (edits take effect immediately, no copy to drift). Idempotent; re-run # after moving the clone, since the links are absolute. # # core.hooksPath is deliberately NOT changed: bd manages its own hooks inside # .git/hooks (pre-commit flushes .beads/issues.jsonl, post-merge imports it) and # moving the hooks path would silently retire them. hooks: @hooks_dir=$$(git rev-parse --git-path hooks); \ root=$$(git rev-parse --show-toplevel); \ mkdir -p "$$hooks_dir"; \ for hook in .githooks/*; do \ name=$$(basename "$$hook"); \ ln -sfn "$$root/$$hook" "$$hooks_dir/$$name"; \ echo "installed $$hooks_dir/$$name -> $$hook"; \ done # One-time setup for this clone (and after any mix.exs gains a dependency): # fetches Hex deps for both apps and the app's JS packages. Needs network, and # is deliberately NOT wired into check/test/verify: `mix deps.get` contacts # hex.pm even when everything is already installed (the advisory check), which # fails offline/sandboxed. The everyday loops run the per-app `deps.check` # guard instead and point here when deps are missing. setup: @$(MAKE) -C app MISE_BIN=$(MISE_BIN) deps @$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) deps # Kept for muscle memory; `setup` is the canonical entry point. deps: setup # Compile the project compile: @make -C app compile # Run tests (app suite + blogex library suite) test: @make -C app test @make -C blogex test # Run Emacs Lisp tests for roam-export-blog (requires emacs on PATH) test-elisp: emacs --batch -Q -l org -l ox-md -l scripts/roam-export-blog.el -l scripts/roam-export-blog-test.el -f ert-run-tests-batch-and-exit # Format code in both apps. Mutating convenience target: `check` (and so # `verify`) never writes. If a gate fails on formatting, run this. format: @$(MAKE) -C app MISE_BIN=$(MISE_BIN) format @$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) format # Serve the app serve: @cd app && mix phx.server # Run Playwright browser-based tests (requires running server) # Set PLAYWRIGHT_BASE_URL to point at the running Phoenix app playwright: @make -C app playwright # Run Playwright in UI mode (headed browser) playwright-ui: @make -C app playwright-ui # Run Playwright against Docker Chrome container (must be running) playwright-docker: @make -C app playwright-docker # Full e2e workflow: start Chrome container, run tests, stop container playwright-full: @make -C app playwright-full # Start Docker Chrome container playwright-docker-start: @make -C app playwright-docker-start # Stop Docker Chrome container playwright-docker-stop: @make -C app playwright-docker-stop