podman builds an OCI image by default and drops the Dockerfile's HEALTHCHECK
instruction, so the first deploy failed at "Wait for the container healthcheck
to pass" with "container ... has no defined healthcheck" even though the app was
up and healthy.
- Declare the same check on the greatbear.container unit (HealthCmd plus
interval, timeout, retries, start period), the convention hops and menu-admin
already use.
- Flush handlers right after starting, before the gate: the unit template's
restart handler otherwise runs at the end of the play, so a run that changes
only the unit would test the stale container.
Mirrors hops 7366596, so the two deployments keep the same shape.
deploy.sh no longer needs a manual push before it, and no made-up tag:
- It pushes the current branch, refuses a dirty tracked tree, and requires
HEAD == origin/main before anything is built, so the image can only be
built for a commit the remote actually has. --force and --no-push skip the
guards.
- The image is tagged :<commit> as well as :latest, and ansible takes
-e image_tag=<commit>, so a deploy pins the exact revision; rollback is the
same play with an older commit.
- Makefile builds `git archive HEAD` instead of cloning the remote (the push
guard makes the local commit the remote state) and defaults PLATFORM to
linux/arm64, because emily is aarch64 — the same default mozimo uses. Drop
build-check-local; build-check already builds the committed tree.
- Makefile: podman build + push instead of docker buildx. build-production
clones the git remote and builds from it; build-check / build-check-local
build without pushing. Single-architecture (PLATFORM-overridable) rather
than a multi-arch manifest.
- deploy.sh: connect as the unprivileged container user; no become.
- ansible: target emily, rootless Podman Quadlet behind the fleet's shared
Caddy unit (caddy/playbook.yml in ansible-playbooks).
- register role writes greatbear.network (NetworkName=greatbear_net) and
the caddy.container.d drop-in that puts Caddy on it.
- greatbear role: podman login/pull, ~/podman-data/greatbear + .env,
greatbear.container (UserNS=keep-id:uid=0,gid=0, EnvironmentFile,
Network, Volume, no published ports), systemctl --user start and a
podman healthcheck gate, with a diagnostics rescue block.
- caddy role appends the site blocks to the shared Caddyfile and reloads;
handlers reload vs. recreate Caddy (a new network drop-in re-creates it).
- drop the network role, the community.docker requirements and the
ansible/files/ templates.
- .containerignore replaces .dockerignore (Buildah reads it natively).
- README: Podman build, rootless Quadlet deploy. No data migration step —
there is no PocketBase state to carry over.
- new ingredients collection (uid, name, emoji icon, diet_class) synced
by update-menu.mjs; menu_items.ingredients is an M2M relation — the
script maps data-file uids to fresh PB record ids
- diet select removed: the green/red FSSAI badge is derived (non-veg when
any linked ingredient is non-veg); 164 items tagged (11 ingredients)
- menu cards render ingredient chips (icon + name) under the description
- migration 1788500200_menu_ingredients.js (idempotent create — app.save
returns nil on success in the JSVM, so don't test its return value)
- .vscode/launch.json: PocketBase + Vite dev, build+preview, menu sync,
full-stack compound (dev PB on :8091 — 8090 is taken on this host)
PB number fields are float64 with onlyInt unset, so storage already
accepted decimals — verified 449.5 round-trips via API with no migration.
Cards now format fractional prices as ₹449.50 (whole rupees stay ₹449);
docs and type comments updated.
- app/src/data/menu-data.mjs: single source for PB sync + offline fallback
- pb/migrations/1788500000_menu_items_v2.js: price number -> text (supports
ranges like 449/549), adds group field for veg/non-veg badges
- scripts/update-menu.mjs: replaces menu_categories/menu_items in any
PocketBase (local dev or https://admin.greatbear.in)
- menu cards: category icons when no image, FSSAI-style dietary badge,
text prices, optional pairing/tag footer
- content.json drops placeholder menu arrays (menu now lives in code)
- playbook.yml (hosts: monoco) + vars/default.yml, requirements.yml
- roles: network (shared docker network), greatbear (registry pull,
bind mount /var/lib/greatbear/pb_data, .env upload, health wait),
caddy (blockinfile snippet into the shared Caddyfile + docker exec reload)
- image honors PB_DATA_DIR and runs as root to match the bind-mount pattern
- frontend on www.greatbear.in (+apex) with /api/* and /_* proxied to
PocketBase; admin.greatbear.in redirects to the admin UI
- TanStack Start (React 19, Tailwind 4) frontend recreated from Stitch design
- PocketBase backend with schema migration + idempotent content seed
- Single Docker image running both services (non-root, healthchecked)
- deploy.sh to build & push to registry.tanshu.com
- Ansible playbook (roles: app, caddy) deploying to www.greatbear.in
with Caddy TLS entries for the site and the PocketBase admin